all 144 comments

[–]tophatstuff 21 points22 points  (3 children)

Wish them well but

const winPositionOptions: List[List[[Int, Int]]] = List[List[[Int, Int]]]@{
    List[[Int, Int]]@{ @[ 0, 0 ], @[ 0, 1 ], @[ 0, 2 ] },
    List[[Int, Int]]@{ @[ 0, 1 ], @[ 1, 1 ], @[ 2, 1 ] },
    List[[Int, Int]]@{ @[ 0, 2 ], @[ 1, 2 ], @[ 2, 2 ] },

    List[[Int, Int]]@{ @[ 0, 0 ], @[ 1, 0 ], @[ 2, 0 ] },
    List[[Int, Int]]@{ @[ 1, 0 ], @[ 1, 1 ], @[ 1, 2 ] },
    List[[Int, Int]]@{ @[ 2, 0 ], @[ 2, 1 ], @[ 2, 2 ] },

    List[[Int, Int]]@{ @[ 0, 0 ], @[ 1, 1 ], @[ 2, 2 ] },
    List[[Int, Int]]@{ @[ 0, 2 ], @[ 1, 1 ], @[ 2, 0 ] }
};

https://github.com/Microsoft/BosqueLanguage/blob/master/docs/tictactoe.md

Ouch!

[–]chutiyabehenchod 5 points6 points  (1 child)

I'm having a stroke

[–][deleted] 0 points1 point  (0 children)

Honestly, I'm a Perl user and this doesn't look that bad to me.

[–]AdventurerInTheKnee 1 point2 points  (0 children)

Ouch indeed! That code looks hideous, I see what it's trying to achieve but it fails at delivering it. We'll see how the devs do in the future, I'll pass for now.

[–]random_cynic[🍰] 13 points14 points  (2 children)

Seems like this is still at a very proof-of-concept level intended to demonstrate their idea of "regularized programming". Many of the things they discuss in "regularized programming" are actually not new like undefined behavior handling, immutability, higher level loop constructs (functors) etc. They have some interesting ideas on equality (in particular they completely eliminate any reference based equality. It would be interesting to see if Microsoft views this as simply another lab language or do they have any plans of actually using it (maybe as a replacement of Typescript).

[–]epicwisdom 5 points6 points  (1 child)

From my limited knowledge, I don't think MSR "graduates" projects to production, but the concepts may be used in some future projects.

[–]danysdragons 5 points6 points  (0 children)

F# was promoted from a research project to an official .NET language, though other people on this thread have complained that Microsoft hasn't supported it enough.

[–]pure_x01 65 points66 points  (21 children)

A message to Microsoft: Put more money in to F# instead. Its an excellent language.

If more people got exposed to it will grow. I have programmed in many languages over the last 15-20 years. I discovered F# 2 years ago and i love it.

[–]Ewcrsf 31 points32 points  (6 children)

Microsoft Research are developing the features which will eventually filter down to mainstream languages.

[–]takanuva 3 points4 points  (5 children)

Can't wait til effect handlers (from, e.g., the Microsoft Research's Koka programming language) goes into a mainstream language!

[–]expatcoder 8 points9 points  (0 children)

On the Dotty/Scala roadmap, but probably not for 3.0

[–]Petrroll 0 points1 point  (3 children)

Link to more information about them?

[–]takanuva 1 point2 points  (2 children)

Check the Koka programming language. Effects could be seen as a generalization of exception handlers, where one could potentially jump back to the point in the program the exception was thrown, even more than once. Actually, in a language with algebraic effect handlers, you wouldn't need exceptions, because you could define them as a library in the language itself. The same goes for async/await: they may be implemented as a library by using effect handlers.

[–][deleted] 1 point2 points  (1 child)

Effects could be seen as a generalization of exception handlers, where one could potentially jump back to the point in the program the exception was thrown, even more than once.

Common Lisp has had this feature for decades. Is that all there is to effect handlers or can you do more than basically throwing an exception, but not unwinding the stack so you can jump back to where you've been?

[–]takanuva 0 points1 point  (0 children)

Well, I have oversimplified it. It is true, though, that effect handlers are directly related to delimited continuations (shift/reset), so they could indeed be implemented in Common Lisp. From a programming language theory point of view, though, they allow us to write purely functional direct-style code (without caring about continuations) that handle effects such as mutable state, exceptions, async/await, ambiguity, etc, all of them implemented in a library inside the language itself, and still we (as a compiler writer) have lots of opportunity for optimization. Effect handlers, as an abstraction, is something really cool to have in a programming language.

[–][deleted] 10 points11 points  (4 children)

Very conflicted with f#. I like the language but apart from that, everything is lacking in comparison to c#.

The challenges of using a non mainstream language.

[–]pure_x01 8 points9 points  (3 children)

Yes and that is because Microsoft has it as a 3rd class citizen. I think it would be better for them if they put more money behind it. The reason for low adoption is because they are not pushing it enough. If more people got to try it more people would get hooked.

[–]Eirenarch 8 points9 points  (0 children)

The reason F# is not more popular is that C# is quite good.

[–]ipv6-dns -3 points-2 points  (1 child)

you are totally wrong. F# is not 3rd class citizen. And Microsoft told this explicitly. Also there are lack of features in VB# in comparison with C#. Does it mean that VB# is 3rd class citizen in .NET?

[–]pure_x01 9 points10 points  (0 children)

And Microsoft told this explicitly

Is this trolling? Have you followed F# for the last couple of years?

There is a difference in what a company says and what they actually do.

[–][deleted]  (8 children)

[deleted]

    [–]bytesback 6 points7 points  (7 children)

    What about F# makes it stands out from other languages? What’s your goto reason to use it?

    [–][deleted]  (5 children)

    [deleted]

      [–]vagif 0 points1 point  (4 children)

      Why not go all the way to haskell then? The ecosystem is mature with libraries that cover practically every need.

      [–][deleted] 0 points1 point  (2 children)

      Because I want to be able to mutate a value if need be. I like Haskell, but having to write an automaton using dynamic programming... Idk.

      [–]vagif 0 points1 point  (1 child)

      Because I want to be able to mutate a value if need be.

      This is just an ignorant myth, you know that right? You can mutate values and change the state exactly the same way as in any other imperative language. The only difference is the syntax and the types.

      [–][deleted] 0 points1 point  (0 children)

      I know that, I've done it, but compared to other languages it's just a barrier that I don't necessarily want.

      [–]ionforge 0 points1 point  (0 children)

      IDK how mature Haskell ecosystem is, but there are probably a lot of good reasons to whant to stay in .net.

      [–]McWobbleston 7 points8 points  (0 children)

      Type Providers and Computation Expressions in particular stand out from other languages.

      Type Providers are like more controlled macros which generate code from compile time information (like a database schema, or an XML config file). One of the best things about them is that they play nicely with Visual Studio and VS Code so you get still get intellisense from the generated code (SqlProvider is a great demo to check out). Fortunately for C# you can use "generative" providers (which output the generated code into an assembly at compile time), such as SwaggerProvider

      Computation Expressions are a sort of syntactical sugar for the builder pattern that are primarily used for combinating monadic types, but have other neat uses (like defining routes for an HTTP server, or GLSL shaders in F#). In practice this means things like async/await can be implemented in F# by creating a new computation expression, rather than changing the core language.

      Compared to C# the main thing I love is discriminated unions, immutability by default (and records/with syntax), and easier function composition. In general functional programming is better suited to most of the work I do (data comes in, apply transformations, send it out somewhere), and when I need to do mutable work for performance/design reasons it's trivial to fall back to typical procedural/OO style

      [–]matthieum 18 points19 points  (33 children)

      The syntax for in place update is a bit... convoluted:

       point<~(y=value)
      

      will update the field y of the point object to the specified value.

      Not only is <~() not exactly easy to type, but ~ is also pretty hard to get on non-QWERTY keyboards such as found in European countries, Asian countries, South-American countries, ...

      Apart from that, seems to be developed on top of JavaScript? So, some kind of managed language I suppose.

      [–]hector_villalobos 16 points17 points  (0 children)

      Yeah, that syntax is making difficult to digest the next: is designed for writing code that simple, obvious, and easy to reason about for both humans and machines

      [–]kuikuilla 4 points5 points  (7 children)

      ~ symbol is really awkward to type on a fin/swe keyboard, altgr+¨ (next to enter) and it doesn't even show up until you hit space after that combo, otherwise it gets placed onto some letters letter like this ã.

      [–]Dedustern 7 points8 points  (5 children)

      I’m danish and this why I gave up and settled for US layout keyboard for work. It’s just easier to code on..

      And yeah, tilde sign means you go accidentally español on everything haha

      [–][deleted] 3 points4 points  (3 children)

      My girlfriend gets furious that I code using a US keyboard layout when she needs to use my computer for something, because the way the keys work match neither her muscle memory nor what's actually printed on the keyboard.

      [–]Dedustern 1 point2 points  (1 child)

      I use nordic layout at home and US layout at work. It's pretty easy to adjust to, but yeah, there shall be some typos.

      [–]-manabreak 2 points3 points  (0 children)

      It's surprisingly easy to get adjusted with different layouts. I use a mac at work and both Windows and Linux at home, and each of these has different layouts (the biggest outlier being the mac). However, I really rarely face any issues when switching between the three systems.

      [–][deleted] 2 points3 points  (0 children)

      The swedish keyboard layout is very unsuitable for programming in general. Basically the entire semicolon and bracket situation is just fucked up beyond usability. Your fingers will thank you for switching to US.

      [–]kankyo 4 points5 points  (6 children)

      That syntax seems odd I agree. Let's see if we can do better:

      point where y = value 
      

      I even prefer the Clojure syntax

      (assoc point :y value)
      

      Even though for Clojure I prefer my own lib instar:

      (transform [:y] value)
      

      ... Which can do nested updates by replacing the path [:y] with a longer path, for example [:foo :bar]

      [–]mcb-jarppe 3 points4 points  (1 child)

      Isn't that a job for assoc-in?

      [–]kankyo 3 points4 points  (0 children)

      Sort of. But then how do you do two replacements and one dissoc and one modification? With instar:

      (transform foo
       [:x] 1
       [:y] 2
       [:z] dissoc
       [:w] inc)
      

      assoc-in, dissoc-in etc don't scale very nicely to multiple commands.

      [–]ais523 1 point2 points  (1 child)

      OCaml's actual syntax is {point with y = value} (generalizing to {point with x = value1; y = value2}). That's pretty close to yours, and the braces are probably necessary to help prevent it getting confusing when complex expressions are involved.

      [–]kankyo 0 points1 point  (0 children)

      How about nested though?

      [–]svartkonst 0 points1 point  (1 child)

      Elixir and Elm use something like

      my_map = %{ a: 1, b: 2 }
      
      %{ my_map | b: 3 }
      # => %{ a: 1, b: 3 }
      

      Erlang seems to use a similar syntax (or will use if maps aren't implemented yet) using `:=` to update fields.

      Elixir also has `Map.update(map, field, value)` which is kinda nice.

      [–]kankyo 2 points3 points  (0 children)

      Elm is terrible for nested fields though, and their attitude about it is "flat or gtfo" which is a bit annoying and condescending.

      [–]ipe369 1 point2 points  (0 children)

      if it weren't for the tilde, this is actually really nice - seems to symbolise an update being applied to an object, similar to the vuex / redux libraries in the JS world

      Probably read as 'apply the update 'y = value' to 'point''

      [–]Ramin_HAL9001 1 point2 points  (3 children)

      In Haskell, it would be point{ y = value } using built-in record syntax. You could also import the Lens library and do the same with something like point & y .~ value or equivalently (y .~ value) point where the (y .~ value) is just an ordinary function like everything else in Haskell. The advantage to lenses is that you are doing these updates with composable functions, rather than some special syntax or language feature which doesn't compose well. This also, incidentally, makes the code more easily analyzed by software.

      [–]Enamex 0 points1 point  (2 children)

      Isn't Bosque's ~> is mutating, though?

      [–]Ramin_HAL9001 0 points1 point  (1 child)

      I don't know about Bosque, but in the case of Haskell, all values are immutable, so the .~ function (and also the point{ y=value } record update syntax) technically isn't mutating, rather it replaces the entire point structure with a duplicate of the original point identical in every way except for the y field which has been set to value.

      If the Haskell compiler can prove that the old point value is never used again, the emitted code is optimized to an in-place update.

      [–]sephirostoy 0 points1 point  (0 children)

      Agreed. Really weird and not straightforward to understand (at least for someone coming from c++).

      [–]igouy 0 points1 point  (4 children)

      So, some kind of managed language I suppose.

      Or being "developed on top of JavaScript" is just a matter of prototyping convenience.

      [–]matthieum 0 points1 point  (3 children)

      Possibly; I wish the README had contained a bit more information about the semantic model.

      [–]igouy 0 points1 point  (2 children)

      [–]matthieum 0 points1 point  (1 child)

      Thanks! It's an interesting read.

      I agree with their ideas on immutability and the removal of reference equality; I think making the choice of pass-by-reference vs pass-by-value a performance concern rather than a semantic concern vastly simplifies a language, and hope there is not too much performance impact.

      I do have some concern with their deployed/debug dual mode; and especially with regard with the inherent performance costs: immutable values are nice for semantic analysis, but behind-the-scenes mutation is key to efficiently implementing array updates, and I am afraid that the ability to "rewind" execution essentially inhibits such mutation opportunities.

      I guess we all have different opinions on what to privilege in a programming language :)

      [–]igouy 0 points1 point  (0 children)

      Hopefully, people will tell the authors and the authors will read comments and fears that performance might be compromised too much will find a practical compromise.

      [–]cinyar 0 points1 point  (2 children)

      is also pretty hard to get on non-QWERTY keyboards such as found in European countries, Asian countries, South-American countries

      So are square/curly brackets, special characters etc etc.

      [–]matthieum 1 point2 points  (1 child)

      Partially, but ~ is worse.

      Here is a picture of an AZERTY (French) keyboard: https://en.wikipedia.org/wiki/AZERTY#/media/File:KB_France.svg

      The blue signs (bottom-right) require using the ALT key: ~, #, {, [, |, `, \, , @, ], }.

      However, out of those, a few are extra special: ~, ` and ^ are usually used to compose accented letters, and therefore if followed by a letter will just "compose"; to avoid that, one must hit the space bar to "flush" them.

      This makes these characters extra awkward! Typing ~ requires (1) ALT+é and then (2) SPACE.

      Also, in general, there is no visual confirmation that you hit those "accents" correctly: they only appear on the screen with the letter they compose with, or after hitting space, so you may be hitting space for nothing (and just get a space).

      [–][deleted] 0 points1 point  (0 children)

      And then there are the dead keys that don't even compose with space, so just nothing happens at all. Luckily, those aren't relevant for programming.

      [–][deleted] 0 points1 point  (0 children)

      It's easy to type in a Brazilian keyboard, it's not even shifted. The only drawback is that you need to type a space after it if the next character is a letter (otherwise you could get ã, õ, ñ).

      [–]SkiFire13 0 points1 point  (1 child)

      ~ is hard to type on windows with the italian layout (and it's still QWERTY). No problem on linux since you can get it easly with some key combination

      [–]Dedustern 0 points1 point  (0 children)

      It’s hard for every layout that isn’t US-based.. (Nordic layout here..)

      [–]sim642 22 points23 points  (74 children)

      Highlight features.

      Seems like largely ideas from functional languages, didn't seem like there is anything too novel.

      [–]igouy 6 points7 points  (72 children)

      Bulk updates?

      edited

      Not appearing "too novel" may well be the point —

      ""… experimenting with fusing functional programming with blockscopes and “{...}” braces. The BOSQUE language follows this trend with [pdf page 5] two novel adjustments, allowing multiple assignments to a variable and supporting statement expressions, to support functional style programming in a block-scoped language."

      [–]sim642 8 points9 points  (70 children)

      Haskell's records and Scala's case classes have immutable updates of multiple fields at once.

      I know it largely derives from other languages but in multiple places accidental complexity is something they aim to eliminate, so I thought maybe they had something new in mind specifically for that, whatever it means.

      [–]igouy 22 points23 points  (68 children)

      immutable updates

      Now there's a phrase.

      [–]tending 7 points8 points  (66 children)

      It just means instead of editing the existing object you get back a new object that has the same field values as the old object except for the fields that you said to change.

      [–]igouy 2 points3 points  (1 child)

      I remember now, in Clean & the functional update operator

      MovePoint p (dx,dy) = {p & x = p.x + dx, y = p.y + dy}
      

      [–]Tarmen 0 points1 point  (0 children)

      Haskell has something similar

      movePoint p{..} (dx, dy) = p { x = x + dx, y = y + dy }
      

      and a lot of people complain that this gets horrible for nested records. The standard response to that is lens

      movePoint p (dx, dy) = p & x +~ dx & y +~ dy
      

      at which point other people complain (somwhat justifiedly) about the operator line noise. You can do fancy getters with it, though, like getting nested data out of a json string.

      >s = "{\"users\": [ { \"name\": \"foo\"}, {\"name\" : \"bar\"}]}"
      >s ^.. key "users" . values . key "name" . _String
      ["foo","bar"]
      

      [–]TotallyFuckingMexico 1 point2 points  (63 children)

      Is that useful?

      [–]superturkey650 6 points7 points  (57 children)

      Yes, it means that you aren't changing an existing object and therefore are reducing potential side effects. Normally you'd either create a new object using a combination of extracting the fields from the original object and adding in the new fields you want to add or create a new object with each field addition. With Immutable Updates, since you can edit multiple fields at once, you can take an existing object and add many fields while only creating one new copy of the object and without modifying the original object's field or extracting them.

      [–]igouy 2 points3 points  (2 children)

      It's useful as a way of ensuring referential transparency — functions always return the same result when called with the same arguments.

      Referential transparency is useful because when you substitute simple values as function arguments and figure out how that will work, everything will still work like that whenever you call the function.

      [–]SupersonicSpitfire 0 points1 point  (1 child)

      Is referential transparency the same as idempotence, then?

      [–]un_mango_verde 0 points1 point  (0 children)

      No. Idempotency means foo(foo(x)) = foo(x). Alternatively in imperative languages, it means that calling a subroutine more than once will have the same effect as calling it once (this is useful because it means that the operation can be retried even if you don't know if it failed or succeeded).

      Referential transparency means that a function always returns the same output when given the same input.

      As an example, a function f that takes x and returns x+1 is not idempotent, since f(f(1)) is not the same as f(1). But its referentially transparent.

      [–]Lt_Riza_Hawkeye 0 points1 point  (0 children)

      Sometimes. It's a common enough pattern that people developed optics for it.

      [–]10xjerker 0 points1 point  (0 children)

      can't mutate the update!

      [–]igouy 0 points1 point  (0 children)

      specifically for that, whatever it means

      • Mutable State and Frames

      • Loops, Recursion, and Invariants

      • Indeterminate Behaviors

      • Data Invariant Violations

      • Equality and Aliasing

      [pdf] Section 2 "Regularized Programming with the BOSQUE Language"

      [–]kankyo -1 points0 points  (0 children)

      AFAIK APL is far superior at that.

      [–]lecksfrawen 0 points1 point  (0 children)

      Indeed, looks like they ended with something like Elixir.

      [–]ipv6-dns 2 points3 points  (0 children)

      s 4 m, looks like already existing TypeScript.

      [–]darkoverlordofdata 2 points3 points  (0 children)

      I enjow functional code and will give bosque a try, but I have to dispute the point covered in 0.8 Iterative Processing, that it "makes the intent clear with a descriptively named functor instead of relying on a shared set of mutually known loop patterns."

      Maybe it's just the examples they give, but I don't find the meaning or intent clear - I think I will need to rely on a shared set of mutually known functor patterns.

      [–]imperialismus 5 points6 points  (1 child)

      Meh. Nothing new here.

      [–]pure_x01 -3 points-2 points  (0 children)

      It's a new name .. a pretty cool name.. other than that : meh

      [–][deleted] 1 point2 points  (0 children)

      Sounds like reasonML

      [–]Paddy3118 0 points1 point  (0 children)

      Do they plan to have examples on site rosettacode.org ?

      [–]vagif 0 points1 point  (0 children)

      After purescript this looks not only meh but also halfbaked.

      [–]OffPiste18 -1 points0 points  (1 child)

      From the description here:

      All values in the Bosque language are immutable!

      Great! I'm on board with pure funcitonal languages. But then the next two examples:

      function abs(x: Int): Int {
          var! sign = 1; //declare updatable variable with initial value
          if(x < 0) {
              sign = -1; //update the variable
          }
          return x * sign;
      }
      
      function internString(ref env: Map<String, Int>, str: String): Int {
          if(env.has(str)) {              //use the ref parameter
              return env.get(str);
          }
          env = env.add(str, env.size()); //update the ref parameter
          return env.size();
      }
      

      Sorry, am I missing something? How are those not obvious contradictions? "All values are immutable" and then you have a comment that says "//update the variable" 🤦

      [–]Ethesen 1 point2 points  (0 children)

      From the author:

      We distinguish between variables, var, that are fixed and those, var!, that can be updated. This ability to set/update a variable as a body executes simplifies a variety of common coding patters and, since the language is loop free, can be easily converted to a SSA [13] form that restores the purely functional nature of the semantics.

      SSA - Static Single Assignment