Thanks for using specific examples, as they are illustrative.

Or, as used in 
https://github.com/drewcrawford/Caroline/blob/edd8aefef44717ecfa03c629100baf095fab983a/caroline-static-tool/main.swift
 to just get access to the exit() function, which is the same across all 
platforms.

exit is an interesting case.  Believe it or not, it is *not* portable, as used 
here.  The C standard defines two constants for its parameter: EXIT_SUCCESS 
(defined to be zero) and EXIT_FAILURE (undefined).  You can pass other values 
(trivia time: only values less than 0377, because the high bits of this integer 
are reserved on some platforms), but the "fail-iarity" or "successiness" of 
values other than the defined two are not specified and may take on different 
meanings on different platforms.  C programmers commonly pick a nonzero value 
to indicate failure (as I did here) – sometimes multiple distinct values to 
indicate different kinds of failure – but this is actually non-portable.

The reason I am being pedantic here is because it demonstrates a broader point: 
people do not actually write portable code; they target either their current 
platform or some vague amalgamation of  2-3 platforms in their immediate 
vicinity.  All the platforms I cared about do something sane with exit(1) so 
it's "portable enough".  But "portable enough" isn't portable.

 In any case, the four lines at the top of your files are almost certainly 
inconsistent on other platforms; for example, do you test for freebsd? Or ps4?

This is a feature, not a bug.  We *like* compiler errors because they give us 
early warning we got something wrong.

I *want* the compiler to stop me when compiling this for OpenVMS.  When I wrote 
this code, I had only Darwin/Glibc in mind, and on that basis, I used exit(1). 
The working assumption is now violated, and the compiler is correct to remind 
me about it.  I don't know, and would need to go find out, what kind of exit is 
sensible for VMS.  Or to move to EXIT_FAILURE like a language lawyer.

But the compile error itself is not a silly annoyance that I would like to 
"solve" by blindly putting more libcs in the list etc. This is a guard rail 
where I indicated the platforms I had in mind when writing this code, and when 
I wake up one morning in a drunken stupor and try to do something else, we fire 
a warning shot.

It's a safety feature, like force-unwrap.  If you're sure it won't blow up, you 
can put an exclamation mark in there and shut up the compiler.  If you're sure 
it's portable to bsd, add bsd to the list and shut up the compiler.  But the 
resolution to this compile error is not to import more libcs.  The resolution 
is to *consider carefully if that is a good idea*.

The assumption embedded in the proposal is that of course we want the program 
to compile, and the question is merely to calculate the set of import 
statements that will achieve compilation, for which the proposal offers an 
algorithm.  My argument is that actually we do not want the program to compile 
unless we are reasonably sure it will work as intended, and the question is 
what syntax allows the author to reasonably encode their assumptions so that 
when they are violated we provide a moment of quiet reflection to consider e.g. 
if exit(1) is sensible on VMS.

The existing system is imperfect (and very ugly) but does a surprisingly good 
job in this dimension.

 It also doesn't seem to support some of the other platforms that might be 
desirable in a test framework, such as iOS, watchOS or tvOS.
I do support iOS (not in this component – it's a command-line tool, so the 
omission of iOS in this file is deliberate, and the compatibility issues go far 
beyond exit).  I don't yet support watchOS or tvOS because I don't have CI for 
those platforms yet and in my view supporting a platform is more than adjusting 
an import statement and wondering if it will compile.

So in summary:

1.  I would not use this feature in the cited examples

2.  I would prefer it if others did not use this feature.  When I see "import 
Glibc" at the top of a file I know what I am signing up for.  When I see 
"import libc" for all I know the developer used Windows.

Finally, this is more of a detail, but I still do not understand how this would 
be implemented for a Linux platform without Glibc, such as Arch.  The current 
proposal has 



  #if os(Linux)

      @_exported import Glibc

which is obviously not going to compile on Arch.  So if the goal is to have 
syntax that is portable the current proposal does not do it.

I do believe there is some room for a more moderate reform on the libc problem. 
 For example instead of the traditional ifdefs, we could have

import? Glibc

import? Darwin


Where the "import?" keyword imports the module if available or otherwise has no 
effect.

This preserves the majority of desireable properties discussed above (clearly 
indicates the intended libcs, provides guard rails similar to the present 
regime) while being significantly shorter than the present regime.  It also 
contemplates problems that the current proposal does not, such as Arch (we can 
continue to list libcs until we find one, and Swift already has rules for 
resolving multiple imports), and it is more broadly applicable to other kinds 
of import problems than libc imports narrowly.

One problem with the import? idea is that it glosses e.g. watchOS/tvOS/macOS as 
"Darwin" when that is not strictly true (posix_spawn for example) but it's at 
least a far more sensible unification than VMS/Darwin.  We do have a clear path 
to check Darwin portability in the compiler (e.g. require @availability(macOS) 
for posix_spawn) while no similar path exists to check Darwin/VMS portability.  
So I think doing something moderate is at least plausible.

Still, it may be a solution in search of a problem.  If you are writing against 
something as badly fractured as POSIX, it should feel like it, and even a small 
unification may be a step too far.

Of course, the real solution to writing portable code is to target a portable 
standard, such as Foundation or some alternative high-level library.
On November 15, 2016 at 10:27:14 AM, Alex Blewitt (alb...@apple.com) wrote:


On 11 Nov 2016, at 03:48, Drew Crawford <d...@sealedabstract.com> wrote:

    grep -R "import Glibc" ~/Code --include "*.swift" | wc -l
    297

As someone who might be characterized as suffering from the problem this 
proposal purports to solve, I am not convinced.

The primary problem here is that "libc" is a misnomer.  Did you mean musl, 
dietlibc, or glibc?  Did you mean "whatever libc my distro likes?"  Swift in 
practice only supports one per platform, but that is a bug not a feature, and 
that bug should not be standardized.  We could try to invent some syntax to 
specify one but now we are back with the current system again.

We're at the current system to start off with, though. When you do "import 
Darwin" or "import GlibC" you're getting whatever the platform has, regardless 
of what you call it. You could call it something else, like "Platform" or 
"Base" but it doesn't change the suggestion itself.

The other problem is that in all my usages, "import Glibc" is not a real 
problem I face.  The real problems are that "the libcs plural" are *just 
different*.  Darwin has timeval64, glibc does not, and you'd better check your 
arch and pick the right one, only on one platform.  SO_REUSEADDR has one type 
in Brand X and another type in Brand Y.  Don't even get me *started* on poll, 
EREs, or half a dozen other behavioral variations.  

Yes, these are issues. Some of them will be worked out with the swift server 
workgroup, or at least standardising Socket as a type which abstracts the 
platform away. But we're at that position at the moment, whether or not there's 
a standard module to represent Darwin/Glibc.

Taking two different libraries and pretending they are the same is not the 
solution, it's the disease.  The way out of this swamp for most developers is 
to use a real Swift library, the same damn Swift library, on all platforms 
(sadly, Foundation today does not meet this requirement).  The way out of this 
swamp for crazy people like me who must write to the metal is to actually write 
to the metal, to the particular libc being targeted, not to a hypothetical 
platonic ideal libc which does not exist.  

I realize that four lines at the top of my files is a *visible* annoyance, but 
fixing it just promotes it to an invisible one. 

Not necessarily, it can be a starting point to fix some of the other problems. 
In any case, the four lines at the top of your files are almost certainly 
inconsistent on other platforms; for example, do you test for freebsd? Or ps4?

https://github.com/drewcrawford/Caroline/blob/26cd0d71e57a62fac6258e4e13dfd6849a1945c6/caroline-static-tool/FileUtils.swift




#if
os(OSX)

import
Darwin

#elseif
os(Linux)

import
Glibc

#endif

So your test framework doesn't work on FreeBSD by default. Yet they've still 
got the same 'write' method. It also doesn't seem to support some of the other 
platforms that might be desirable in a test framework, such as iOS, watchOS or 
tvOS. You'll just get silent errors on those when it's used on those platforms. 
And as new platforms get added, your code will slowly drift further away from 
supporting everything to supporting a few known values.

Now granted, some of these may have yet more incompatible versions for 'write' 
which needs handling specifically. That's bad, and it should be something that 
can be worked on. But most of the other functions (like 'close') don't need 
handling specifically. Or, as used in 
https://github.com/drewcrawford/Caroline/blob/edd8aefef44717ecfa03c629100baf095fab983a/caroline-static-tool/main.swift
 to just get access to the exit() function, which is the same across all 
platforms.

Other proposals - such as Johannes' treatment of how to handle errno - will 
help work around these problems. Perhaps we end up with a generic write 
function that wraps the platform specific one to abstract that away as well, 
which reduces these issues one by one.

Alex
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to