Made with KolourPaint and screenshots from Kate (with the GitHub theme).

  • ThirdConsul@lemmy.ml
    link
    fedilink
    arrow-up
    2
    ·
    5 hours ago

    To be honest I always disliked variable declaration without value assignment, so to me both options suck. :)

    • notarobot@lemm.ee
      link
      fedilink
      arrow-up
      1
      ·
      edit-2
      13 minutes ago

      What about

      Let ret: Number
      If (someCondition) {
          <a lot of expensive calculations>
          ret = resultOfOperations
      } else {
          <a lot of other different expensive operations>
          ret = resultOfOtherOperations
      }
      return ret
      

      You can’t declare ret inside the brackets

    • CarrotsHaveEars@lemmy.ml
      link
      fedilink
      arrow-up
      1
      ·
      4 hours ago

      What about you declare (then it gets allocated in stack) it and pass it to a different context for assignment?

      • ThirdConsul@lemmy.ml
        link
        fedilink
        arrow-up
        1
        ·
        edit-2
        30 minutes ago

        Well, I don’t know your use case well enough, but I guess you might have perfect reason for that behavior.

        One thing that comes to my mind is the old Try in C#

        bool parsedSuccessfully = int.TryParse("123", out int result);
        

        But I guess more popular approach would be to use Error as Values, right?

        E.g. something like this

        Outcome<Exception, Int> result = int.TotallyNewParse("123");
        
  • ByteWelder@feddit.nl
    link
    fedilink
    English
    arrow-up
    3
    ·
    9 hours ago

    In Kotlin, you can have the type become implicit with the former syntax: let text = number.toString() (text is a String here)

  • PowerCrazy@lemmy.ml
    link
    fedilink
    English
    arrow-up
    7
    arrow-down
    1
    ·
    14 hours ago

    Enlightenment is realizing that variables don’t have nor need a type, they are all just arrays of bits.

    • balsoft@lemmy.ml
      link
      fedilink
      arrow-up
      9
      ·
      9 hours ago

      True enlightenment is realizing that variables don’t exist, it’s all just a sequence of bits in RAM that we assign meaning to as desired.

      Ascension is realizing that bits don’t exist, it’s all just trapped electrons in transistors which we imagine to be bits.

      Transcendence is realizing that transistors or code doesn’t exist, and it’s just some quarks and electrons attracted and repulsed by weird forces, vibrating and convulsing in a soup with entropy constantly rising until the heat death of the universe, of which we make futile attempts to make sense or purpose.

  • charje@lemmy.ml
    link
    fedilink
    arrow-up
    13
    ·
    18 hours ago

    well, the : String is supposed to be optional right? type inference should know what it is. In truth though, return type polymorphism makes us write more type annotations than I would like.

  • Oriel Jutty :hhHHHAAAH:@infosec.exchange
    link
    fedilink
    arrow-up
    16
    ·
    21 hours ago

    Because let x: y is syntactically unambiguous, but you need to know that y names a type in order to correctly parse y x. (Or at least that’s the case in C where a(b) may be a variable declaration or a function call depending on what typedefs are in scope.)

    • HiddenLayer555@lemmy.mlOP
      link
      fedilink
      English
      arrow-up
      10
      arrow-down
      1
      ·
      edit-2
      20 hours ago

      Can’t say I’ve ever experienced this kind of confusion in Java but that’s probably because they intentionally restricted the syntax so there’s no ambiguity.

    • Gamma@beehaw.org
      cake
      link
      fedilink
      English
      arrow-up
      4
      ·
      edit-2
      20 hours ago

      Also useful when the types are optional, like Python. Though they don’t use any let or var or anything so maybe throw that entire point out the window

  • Shanmugha@lemmy.world
    link
    fedilink
    arrow-up
    8
    ·
    19 hours ago

    My attempt of an honest answer to my best knowledge:

    As @[email protected] mentioned, to make a programming language closer to spoken English language, most likely (hi, Python, I am looking at you too). Which infuriates me immensely: when programming, I do not speak languages, I express data structures and operations on them, stacked one upon another. The last thing I need here is ambiguity, loose structure and information duplication (forgot correct term for the last one) that are typical to natural languages of human communication

  • TootSweet@lemmy.world
    link
    fedilink
    English
    arrow-up
    6
    ·
    edit-2
    17 hours ago

    The Go programming language documentation makes a big deal about how it “reads from left to right.” Like, if you were describing the program in English, the elements of the Go program go in the same order as they would in English.

    I say this as someone who likes Go as a language and writes more of it than any other language: I honestly don’t entirely follow. One example they give is how you specify a type that’s a “slice” (think “list” or “array” or whatever from other languages) of some other type. For instance a “slice of strings” would be written []string. The [] on the left means it’s a slice type. And string on the right specifies what it’s a slice of.

    But does it really make less sense to say “a string slice”?

    In Go, the type always comes after the variable name. A declaration might look like:

    var a string
    

    Similarly in function declarations:

    func bob(a string, b int, c float64) []string { ... }
    

    Anyway, I guess all that to say I don’t mind the Go style, but I don’t fully understand the point of it being the way it is, and wouldn’t mind if it was the other way around either.

    Edit: Oh, I might add that my brain will never use the term “a slice of bytes” for []byte. That will forever be “a byte slice” to me. I simply have no choice in the matter. Somehow my brain is much more ok with “a slice of strings”, though.

    • Both of those declarations look weird to me. In Haskell it would be:

      a :: Stringbob :: (String, Int, Double) -> [String]bob (a, b, c) = ...
      

      … except that makes bob a function taking a tuple and it’s much more idiomatic to curry it instead:

      bob :: String -> Int -> Double -> [String]bob a b c = ...-- syntactic sugar for:-- bob = \a -> \b -> \c -> ...
      

      The [T] syntax also has a prefix form [] T, so [String] could also be written [] String.

      OCaml makes the opposite choice. In OCaml, a list of strings would be written string list, and a set of lists of strings would be string list set, a list of lists of integers int list list, etc.

    • bleistift2@sopuli.xyz
      link
      fedilink
      English
      arrow-up
      5
      ·
      19 hours ago

      But does it really make less sense to say “a string slice”?

      That’s an interesting point. You say “a pizza slice” or “a slice of pizza”, but you only say “a slice of bread”, not “a bread slice” (right? I’m not a native speaker).

      • charje@lemmy.ml
        link
        fedilink
        arrow-up
        2
        ·
        18 hours ago

        its makes more sense to say “a pizza slice”. using “of” in this way is from french.

        • Eager Eagle@lemmy.world
          link
          fedilink
          English
          arrow-up
          3
          ·
          18 hours ago

          personally, I’ve heard a lot more “bottle of water” than “water bottle” in the US

          this “reads from left to right” really doesn’t hold up

          • melvisntnormal@feddit.uk
            link
            fedilink
            arrow-up
            2
            ·
            4 hours ago

            This might be getting into the weeds a little, but to me, “bottle of water” implies a single-use bottle already filled with water, while “water bottle” implies a bottle that is made to be (re)filled with water

      • TootSweet@lemmy.world
        link
        fedilink
        English
        arrow-up
        1
        ·
        edit-2
        17 hours ago

        Yeah, I think “a slice of bread” is a lot more common than “a bread slice”. Not to say I haven’t ever heard “a bread slice” used. I’m sure I have at least a few times. It would be pretty rare, however.

        Though, I’m not sure “a pizza slice” is all that much more common. Maybe there are regions where it’s very common? Or maybe it’s more common in certain contexts? Like maybe sell-by-the-slice pizza places might tend to refer to “a pizza slice” rather than “a slice of pizza” when talking with coworkers? (That said, I’d imagine they’d just shorten it further to “a slice” since the “pizza” part would tend to be obvious in that case.)

        Also, @[email protected] mentioned “water bottle”. I think if I hear “a water bottle” rather than “a bottle of water”, I’m probably going to assume it may or may not be an empty bottle intended for water rather than a bottle filled with water as “a bottle of water” would imply.

        Way off the topic of programming, but linguistics is fascinating too!

    • sph@lemmy.world
      link
      fedilink
      arrow-up
      1
      ·
      edit-2
      17 hours ago

      Go’s syntax is vastly superior once you have more complicated signatures, then the left-to-right truly matters. For example a variable that contains a pointer to a function that takes a function and an int and returns another function (like a decorator).

      In C the order becomes very hard to understand and you really have to read the thing several times to understand the type of fp:

      int (*(*fp)(int (*)(int, int), int))(int, int)

      In Go, you can just read from left to right and you can easily understand what f’s type is:

      f func(func(int,int) int, int) func(int, int) int

      It’s just much more readable.

      See: https://go.dev/blog/declaration-syntax

        • sph@lemmy.world
          link
          fedilink
          arrow-up
          1
          ·
          edit-2
          2 hours ago

          True, but that requires writing an additional definition and hides the parameter types, which can be very interesting, and you’d need a typedef for every new param combination I guess. It feels like a solution for a problem that could have been avoided by a better signature syntax in the first place.

        • ThirdConsul@lemmy.ml
          link
          fedilink
          arrow-up
          1
          ·
          5 hours ago

          Wait until you learn about transducers (Are they in Go? If not natively, someone definitely ported them) and the abominations fp people code with them.

        • sph@lemmy.world
          link
          fedilink
          arrow-up
          2
          ·
          edit-2
          6 hours ago

          This obviously just illustrates a point, but callbacks and decorators are not uncommon. And iterators are exactly like that:

          type (
          	Seq[V any]     func(yield func(V) bool)
          	Seq2[K, V any] func(yield func(K, V) bool)
          )
          

          Which is very readable.

          • phlegmy@sh.itjust.works
            link
            fedilink
            arrow-up
            1
            ·
            5 hours ago

            Callbacks and decorators are fine, but callbacks/decorators to a function which itself takes a function pointer and returns another function pointer are crazy.

            I’ve thankfully never had to use recursive callbacks or decorators, but it seems like it could very quickly become difficult to keep track of.

            • sph@lemmy.world
              link
              fedilink
              arrow-up
              1
              ·
              edit-2
              2 hours ago

              I don’t think it’s that uncommon. Let’s say you have a function that handles a request. A common use case is to add permission checks before applying that function. You can write a generic permission check a bit like this:

              func NeedsPermission(f func(Request) (Response, error), perm string) func(Request) (Response, error) {
                  return func(r Request) (Response, error) {
                      if !check(r, perm) {
                          return nil, NewPermError(perm)
                      }
                      return f(r)
                  }
              }
              
              // elsewhere
              Bar := NeedsPermission(Foo, "superman")
              

              This would allow you to separate the permission check logic from the business logic. Though to be fair, in Go they prefer to keep things as simple as possible but it’s just to illustrate that these concepts are not that alien.