9

In my latest installment of "Swift, WTF?", we look at the "if" conditional in terms of the Swift convention of:

if let x = y { /* ... */ }

so what this does :
1. declares x in the scope of the braced code
2. sets x to y (an ahem, "optional")
3. decides if x is not *nil*, then executes the braced code.

This is very similar in both the visual and the operation to the C code of:

if (int x = y) { /* ... */ }

1. declares x in the scope of the braced code
2. sets x to the value of y
3. if x is not zero, then executes the braced code

which is considered *exceptionally* poor style.

Neither the C nor the Swift construct result in a legitimate boolean value of "true" or "false", although C comes closer than Swift.

In the Swift case the *imaginary* "nil" value has to be interpreted as "false" and thus there must be extra code is for the conditional to check on whatever constitutes the **actual** value of nil in Swift and then set the condition to "false".

(remember boys and girls, "optionals" are not real, they are an imaginary language construct of Swift and have no legitimate counterpart in the CPU operations with memory and registers)

At least in the case of C, if the value of x is zero or NULL (which is 0) then it is technically a "false" which in C is 0. Regardless, it is really poor programming and anyone doing that on my team gets an ear full.

But in Swift this obfuscation of code is common and condoned! Well, why not put more of the program in the condition of the if? In fact, stuff the whole thing in there.. why not? 🙄

This just reenforces my opinion that Swift is not a bird but the stuff that comes out of the underside of the bird. 🐦💩

Comments
  • 3
    Ya can do it in python too. Meet the walrus operator.

    if (x := y - 1):
    ...
  • 5
    Thing is, I always found this shit ultimately stupid (unless some corner cases related to multithreading with have better solutions anyway).

    Why would you branch on an assignment?

    Just fucking branch on the RHS to begin with...

    Locality of the variable? Maaaaaaybe. But I still think branching on an assignment is a terrible code smell.

    Fucking branch on y and operate on y. Unless y is a reference type (in which case equality is always false (unless it's the same object which has its use cases but most likely is a debauchery) or custom defined).

    In C it's not poor style, it's downright dangerous. Dunno about swift, but from what I've heard, shouldn't be a problem, but it's still a poor choice.
  • 4
    I don't see how this is worse than the C version. I don't know swift specifically, but I would assume that optional is either a tagged union or a nullable reference, both cases should result in exactly the same optimized machine code as the corresponding C technique for value and reference types respectively.
  • 5
    @atheist walrus operator rocks. Looks cute as well.
  • 2
    I also don't see why either is bad form. They hide a minuscule amount of behaviour, much less than is lost or gained from arbitrary reordering of non-inlined calls to functions that use different registers, they don't hide any usercode dispatch, they branch on the structure of a container. You can also use the C construct incorrectly like everything in C but its correct use involves a trivial datastructure containing either a 1-based ID such as a pointer or nothing
  • 2
    @CoreFusionX I think it's pretty nice to be able to assign in a loop, I kinda see the point with conditional but less so.
  • 3
    Booleans are exactly as real as optionals too. The dumb tagged union implementation of an optional is literally a boolean, and the nullable reference implementation is created the same way a boolean is created, by assigning one meaning to one subset of the possible values of a number, and a different meaning to another. The main difference is that optionals are a distinct concept so the compiler can choose even more efficient implementations for special cases, such as by niche elimination.
  • 4
    That looks absolutely horrible. Burn it
  • 1
    @atheist fun fact, ALGOL is where ":=" started and it was popularized by Pascal circa 1970.

    While I think it is kinda cool it is called the walrus operator, it is pronounced "set equal" where the colon is where the hands of the sprinter are on the track, the = is where the sprinter's feet are. Ready "set" go.. hence ":" is the "set".

    Goo goo g' joob?
  • 1
    @lorentz Booleans are exactly as real as optionals too

    I have not run the Swift construct down machine code or assembly yet, but the thrust is that optionals don't exist at the CPU level... the computer's machine code. It takes extra multiple lines of machine code to implement such a concept. A boolean in C is nothing more than a compare to 0 or not zero when it hits assembly. Exceptionally efficient down to the CPU cycle per machine code instruction level.

    I have not investigated booleans in Swift at the assembly level yet, but what you said about booleans in Swift makes me apprehensive at an OCD efficiency level. 😱
  • 2
    @xcodesucks What you describe as "taking multiple lines of machine code" (which is not a useful distinction at all given how many factors affect the performance of machine code) is either a nonzero or an iszero check which is the same cost as a boolean true check, followed by an assignment to local which doesn't exist in assembly and serves purely to encode the value flow graph used by both the compiler and the author in a way that's easy to read by a second human. This is the case whether the optional is translated to a tagged union or a nullable reference. I pointed out that booleans don't exist because you attempted to describe how inefficient the conditional assignment is by pretending that _nil has to be cast to false_ in machine code, an exceptionally funny preposition where neither of the operands, nor the operation actually exists in machine code.
  • 2
    @retoor The use of : in programming (for types) made me sick, it's why I didn't consider kotlin nor typescript a real language, but I have been cudgeled to use them and can definitely see their benefit over the base languages even if I still prefer those in the end

    Then again I do think the { should be removed from most languages together with the ; for line endings. Ohno ambiguity on line endings, well maybe just don't write shit code here is a fucking error try it again.

    Also := will be colon equals to me @xcodesucks thanks to Go
  • 2
    Just to clarify, this code is equivalent to this?

    if (y)

    {

    x = y;

    // Do stuff with x without modifying y

    }

    I still cannot wrap my head around the SWIFT code. Maybe SWIFT should focus on getting a proper garbage collector, instead of all this syntax sugar.

    I think SWIFT is a polished turd. Looks nice from the outside, but it's still crap.
  • 1
    @BordedDev 'kotlin' is a ketchup brand...

    also a city in Poland.
  • 1
    @D-4got10-01 Nice I like ketchup. My favourite as a kid was, macaroni layer of ketchup topped with cheese, so the ketchup doesn't dehydrate. But I hear it's good in soup to.

    You don't have one called mustard do you?
  • 1
  • 1
    @lorentz I also don't see why either is bad form

    Think of this.. it's not uncommon to see C programmers do this...

    if( ptr ) {/* */}

    - technically exercises the knowledge that 0 is the definition of "false" at the machine code level & any other value is "true". It translates to "if the pointer is not nil then".

    But it relies on a side effect of the C language at the time. There is no guarantee that in the future version of C won't define 1 as true and 0 as false and the such code could then have an "undefined" in the conditional.

    In reality, it should be:

    if( ptr != NULL ) {/* */}

    - which is self documenting ;-)

    This parallels Swift which **assumes** that "nil" is false in the

    if( let x = y ) {/* */}

    as the let x = y executes and leaves behind the x as in:

    let x = y

    if( x != nil ) {/* */}

    and this discretely performs a legit boolean check, is truly self documenting, and is easily debuggable.
  • 1
    @BordedDev Re: Also := will be colon equals

    or ... we call it SKYRIZI!

    (sorry, the 14 yr old still lives inside)
  • 1
    @xcodesucks I see what you mean about C, but that's not what happens in Swift at all. "if let" is _defined_ in terms of optional. It doesn't assume anything about the implementation or truthiness of either, no boolean is ever created, no if statement is ever executed. "if let" shares a keyword with "if" because of their shared purpose of conditional execution.
  • 2
    @xcodesucks

    Actually, you are wrong there.

    C has no concept of null, nil, or whatever else you want.

    It's defined, by spec, that in integer boolean evaluation 0 is false and anything else is true. Pointers are just ints and follow the rule.

    While C could redefine booleans, it's such a far fetched scenario as to consider it impossible.

    And even then, you proceed to say the correct way is comparing against NULL, which in both C and C++ is a preprocessor macro that substitutes to 0. (And like any other macro, is trivially redefined to cause havoc).

    C++ (sanely) recommends to use nullptr, which is a language level constant that only applies to pointers.
  • 2
    Of course, neither the C nor C++ standard can just switch the meaning of boolean logic.

    That's the biggest ABI change ever, which is technically possible, but would force C++27, and then either everyone would avoid it because retardedness, like JavaScript, or just stick to non retarded language versions.

    And then again, what stops crapple from doing the same with Swift?
  • 1
    actually yeah, the "if" statement could also be redefined to keep re-running its body as long as the argument is true, breaking every program in existence, and it would be exactly as stupid as the change you're preparing for.

    In terms of correctness, a change is a change, big or small. In terms of practicality, people rely on if statements accepting numbers greater than 1. If that was redefined as UB, most real-world programs would translate to an empty executable.
  • 2
    *sigh* this has nothing to do with booleans and evaluation to false/true.

    It’s conditional binding.

    if let x = y { }

    if y is not null, x will be a non optional in the following scope.

    It’s a convenient and safe way to deal with optionals.

    Because if you check for nil traditionally,

    if y != nil {}

    you need to deal with the optional y in the scope, which is stupid because you already checked it and you know that it‘s not nil.

    Kotlin uses smart casting for that.
    Swift uses this "if let" syntax.

    Stop applying C language logic to a language that you are not familiar with.
  • 0
    this syntax is literally:

    If this optional variable has a value (not nil), cast it to a non optional variable with that value and provide it as a new variable within that scope.

    Which conveniently means:

    If that thing has a value, let me do a couple of things with it.

    Instead of the inconvenient alternative of:

    Check if it has a value, do something with it,
    then do something else with it, but first check for nil again, because it‘s still an optional, then check for the third time for nil to do a 3rd thing with it.
Add Comment