News for hackers. Stuff that matters.
Re:Grain: A strongly-typed functional programming language f... by tlrobinson on Tuesday July 31, 2018 @01:44AM (#17650809)
The main page doesn't do a great job of showing what's interesting about Grain vs. JavaScript. The only hint is this: "No runtime exceptions, ever. Every bit of Grain you write is thoroughly sifted for type errors, with no need for any type annotations."

Maybe show some examples of errors Grain would catch that JavaScript wouldn't, like Elm does: http://elm-lang.org/

Re:Grain: A strongly-typed functional programming language f... by repsilat on Tuesday July 31, 2018 @02:16AM (#17650941)
> No runtime exceptions, ever.

This is something I wonder about JS: there are a lot of places that exceptions happen in (say) Python that just return `NaN` or `undefined` in javascript. Is it intentional? Is it a good idea?

Examples: the multiplication operator essentially never throws. Out-of-bounds (or "not found") lookups don't throw.

I suspect the logic is "only throw if you have the wrong type for that operation" -- like calling something that isn't a function, or looking up an attribute on something that isn't an object. (Except multiplication for things that aren't numbers is fine, I guess...)

I'm writing a dynamically typed language and don't know if it's better to go the JS way or the Python way. Or do something horrible like having multiplication return a `Maybe` type...

Re:Grain: A strongly-typed functional programming language f... by zachrose on Tuesday July 31, 2018 @03:06AM (#17651125)
Yeah in general it’s good to avoid sometimes returning a value and sometimes undefined.

There’s an equivalence you can make between a type and a mathematical set, where you say that the type is the set of all possible values for that type.

In both JavaScript and math, multiplication of numbers is an operation that has a special property called closure, which means that the return type is the same as the input types. Multiply a number by another number and you will ALWAYS get a number back. The inputs and the outputs are in the same set, which means you can go nuts multiplying numbers and you’ll never have to check your values to make sure they’re still numbers; it can be safely assumed.

JavaScript gives NaN a type of “number” as a clever compromise. Instead of throwing an error when multiplying a number by a non-number, JS allows multiplication to still return a “number” (`4 * ‘a’ === NaN`) and then you don’t need to ever worry about accidentally “leaving” the set of numbers (`NaN * 10 === NaN`).

More likely than not though, multiplying a number and a string is just not a useful thing to do. With a good type system, a program that could wind up in a situation of multiplying a string and a number can be rejected by the compiler.

So in a roundabout answer to your question, a lot of “what then?!” situations can be entirely avoided with a good type system. For the remaining situations like accessing an element in an array that may not exist, a Maybe can make a lot of sense.

(Maybe Float turns out to be just like JavaScript’s numbers, but instead of NaN you have Nothing.)

Re:Grain: A strongly-typed functional programming language f... by kazagistar on Tuesday July 31, 2018 @10:13AM (#17653270)
Closure is only good in programming if the answers it gives are always useful. Otherwise, you run into the same non local error problem that plagues nulls: the error still happens, but now it happens at some distant usage site, far away from the cause.
Re:Grain: A strongly-typed functional programming language f... by zachrose on Wednesday August 01, 2018 @07:16PM (#17667932)
Good point. This is exactly what JavaScript does with NaN and the set of numbers, and errors are harder to track down because of it.

Computer numbers in general have all sorts of issues like this where clean mathematical theory is broken. NaN, Infinity and -Infinity, for example, are all similar to absorbing elements[1] under multiplication in the sense that once you get that as a result, you can't do the inverse operation (division) to get back to your original inputs.

Re:Grain: A strongly-typed functional programming language f... by lomnakkus on Tuesday July 31, 2018 @02:43AM (#17651042)
The JS way is a mistake, intentional or not.

Here's a little thought experiment: Your program ends up with an "undefined" in some variable 'x'. How did that happen? In JS it can happen in any number of weird and wonderful ways, e.g. you called a function which did a 'v[i]' or it could have just fallen off the end because someone forgot to check a return path, or...

In Python there's much less scope what the problem could be. Since v[i] will just throw an IndexError, you know that the problem couldn't possibly be stray index or similar.

That is a much better experience for finding problems in one's code.

Re:Grain: A strongly-typed functional programming language f... by millstone on Tuesday July 31, 2018 @03:07AM (#17651129)
But JS programs must execute in uncontrolled environments, e.g. browser engines from the past and future with random extensions installed. A bondage-and-discipline language may help developers find logic bugs, but will make the users' experiences worse.
Re:Grain: A strongly-typed functional programming language f... by lomnakkus on Tuesday July 31, 2018 @03:52AM (#17651329)
How is "there was a JavaScript error on this page" informational icon any worse than an order total of "undefined" or that the page just doesn't seem to be reacting to clicks? I'd argue that the former is much better UX -- at least the user isn't confused whether it's them that's doing something wrong or it's the page that just shoddily implemented.
Re:Grain: A strongly-typed functional programming language f... by codetrotter on Tuesday July 31, 2018 @06:57AM (#17652095)
> at least the user isn't confused whether it's them that's doing something wrong or it's the page that just shoddily implemented

Users generally ignore all messages coming from their computers. They routinely blame their computers for doing things that the computers are not doing at all. Like, oh I can’t find the document I wrote three weeks ago -> obviously my computer is being disobedient.

Anyway, I don’t blame the users. To them the computer is entirely uninteresting and they don’t want to care about the sorts of concerns that we technically minded people do.

A broken page is a broken page and it doesn’t matter to the user why the page is broken. The only thing that matters to them is, can they do the thing they wanted to do or not. And like the sibling said, the web browsers are surprisingly good at handling broken code.

Re:Grain: A strongly-typed functional programming language f... by lomnakkus on Wednesday August 01, 2018 @04:07PM (#17666453)
Did you read what I said at all?

"Order total: undefined" is hugely different from "There was an error -- maybe just leave the page, yeah?".

Re:Grain: A strongly-typed functional programming language f... by millstone on Tuesday July 31, 2018 @05:07AM (#17651633)
Banker vs moon rover. B&D languages panic at the first whiff of deviation between the compile-time and runtime environments. But I loaded cnn.com, and my third-party ad blocker did god-knows-what to dozens of requests, with a bazillion unexpected undefineds, and yet the page still rendered.

The web powers through!

Re:Grain: A strongly-typed functional programming language f... by lomnakkus on Tuesday July 31, 2018 @12:40PM (#17654647)
This has nothing to do with undefined vs. exceptions, sorry. You can do example the same with a powerful enough sandbox -- e.g. what WebAsm does to avoid hostile code taking over your computer.

It has everything to do with sandboxing (or not). Ads being served by third parties should not be able to influence the JS running in the page.

Re:Grain: A strongly-typed functional programming language f... by jvtbatman on Wednesday August 01, 2018 @05:45AM (#17661010)
Generally, I'd say that the less strict the compiler/interpreter is, the worse code you'll end up with. In my experience, Python needs a lot of external checks (i.e. linting, static analysis) to help the programmer write code that actually work as intended (and JS probably is worse).

As John Carmack said: "...if you have a large enough codebase, any class of error that is syntactically legal probably exists there."

Re:Grain: A strongly-typed functional programming language f... by barrkel on Tuesday July 31, 2018 @07:46AM (#17652381)
It's generally better to highlight the existence of an error condition sooner rather than later.

Compile time is better than runtime, evaluation time is better than via explicit value inspection.

Non-signalling NaNs provide an easy way of distributing an invalid value widely throughout a program's data structures before it's discovered.

The only reason to go the other way, and have silent NaN propagation, is if they're expected to occur very frequently. For example, consider how awkward SQL would be if evaluating over null values triggered errors - the conditionality of expressions would need to become very elaborate.

Monadic approaches to errors (Maybe, Rust's Result, that conditionally apply a function to a value only if it's not an error) blur the line between these two. Because they rely on data flow, they feel a bit like non-signalling NaNs. OTOH, evaluation generally bubbles up using monadic return types, and errors bubble up too, just like exceptions - exceptions, and consistent, universal use of monadic return types, are isomorphic and can have the same evaluation characteristics.

Re:Grain: A strongly-typed functional programming language f... by _hl_ on Tuesday July 31, 2018 @01:20PM (#17655057)
> exceptions, and consistent, universal use of monadic return types, are isomorphic and can have the same evaluation characteristics.

I feel like there is a small but important difference. Encoding exceptions in monadic return types allows the type system to guarantee that all exceptions are handled, or at least considered by the programmer. That is a very strong guarantee, especially as you put up layers and layers of foreign libraries and abstractions.

Re:Grain: A strongly-typed functional programming language f... by crimsonalucard on Thursday August 02, 2018 @07:34PM (#17676320)
NaN is property of the floating point specification.

https://en.wikipedia.org/wiki/NaN

The purpose of silent propagation is for the expression to be checked at the end of the overall expression rather then have every operation itself be checked. It's a speed optimization. It is by far more user friendly for an invalid operation to throw an error.

For example

for this following operation

(100/2/2/0/2)

without NaNs the system must check 4 operations 100/2, 50/2, 25/2, 12.5/0 for an error. Every arithmetic operation whether it has a division by zero or not will have to have additional checks.

With NaNs the computer just runs through the entire operation with no checks and the user just explicitly does a check for a single NaN at the end. The Maybe Monad operates under the same concept when used as an output type for a division operation.

The same logic applies for javascript "undefined".

Re:Grain: A strongly-typed functional programming language f... by masklinn on Tuesday July 31, 2018 @08:35AM (#17652630)
> This is something I wonder about JS: there are a lot of places that exceptions happen in (say) Python that just return `NaN` or `undefined` in javascript. Is it intentional? Is it a good idea?

Yes and no respectively.

It's intentional in the sense that the original Javascript was not intended to fault (much) because it was for basic scripting, so if one small script blew up it should not bring down the entire page's scripting. This also resulted in Javascript's exceptions facilities being very shitty (exception handling is not very flexible/convenient, and while that may have changed since — not sure — for a long time it was impossible to sub-type the native Error).

However it's not really a good idea for non-trivial software systems, it makes errors much harder to notice, recover from and debug. In fact "modern" JS APIs tend to fault e.g. parsing invalid JSON raises SyntaxError, it doesn't return null or undefined; and promises and async functions will convert exceptions to failures.

Re:Grain: A strongly-typed functional programming language f... by repsilat on Tuesday July 31, 2018 @04:08PM (#17656622)
Invalid JSON parsing as `null` would be an exciting API decision, haha.

One thing I think I like about JS over Python is that empty containers are "truthy". This, combined with non-raising missed lookups, tends to be pretty ergonomic. For me, at least.

Though it is messier -- in Python `key in d` is well entrenched as an idiom, and in JS `if(d.key)` misfires if the value is zero, and `if(d.key === undefined)` doesn't discriminate between a missed lookup and a stored `undefined`. Though the latter must be discouraged, right?

Re:Grain: A strongly-typed functional programming language f... by masklinn on Wednesday August 01, 2018 @04:10AM (#17660475)
> Invalid JSON parsing as `null` would be an exciting API decision, haha.

PHP's json_decode does that. And yes `null` is also returned as a PHP NULL.

> Though it is messier -- in Python `key in d` is well entrenched as an idiom, and in JS `if(d.key)` misfires if the value is zero

Or false, or null, or the empty string, or NaN.

FWIW `if (key in d)` also works in JS if d is a native object, though you need `d.has(key)` if d is an actual Map object instead.

Re:Grain: A strongly-typed functional programming language f... by setr on Tuesday July 31, 2018 @02:37AM (#17651019)
I would argue to throw; there's not much good that comes out of intentionally having an error cascade through the program until reaches a throwable error, or produces incorrect results (this is true for both python and js, but the decision you're making is to allow it more than absolutely necessary for a dynamic lamguage)
Re:Grain: A strongly-typed functional programming language f... by galaxyLogic on Tuesday July 31, 2018 @11:16AM (#17653823)
I think JavaScript simply got it quite wrong by trying to be way too clever. In theory it is fine to say that dividing by 0 is Infinity but what can you do with Infinity?

In practice that causes the output of your program be either Infinity or NaN but the problem is that is usually never what you want.

Then you want to know "Why do I get a NaN here?" and you will have to study all of your program and single step its execution to understand why you got an answer you din't want which is of little value to anybody.

Problem with Infinity is you can not come back from there. It does not cancel out if you subtract it.

Instead IN PRACTICE it is much better to catch errors early with the help of the type-system, unit-tests, and assertions.

It is an interesting challenge: How do I define the type "Any number except zero" and have my type-system then catch divisions by zero?

Re:Grain: A strongly-typed functional programming language f... by recursive on Tuesday July 31, 2018 @12:06PM (#17654379)
> I think JavaScript simply got it quite wrong by trying to be way too clever. In theory it is fine to say that dividing by 0 is Infinity but ...

This wasn't javascript's idea. They're just following the spec. https://en.wikipedia.org/wiki/IEEE_754#Exception_handling

Re:Grain: A strongly-typed functional programming language f... by galaxyLogic on Tuesday July 31, 2018 @11:04PM (#17659328)
This IEEE spec is about Exceptions like exception for division by zero. As far as I can tell dividing by zero in JavaScript does not cause an exception, does it?
Re:Grain: A strongly-typed functional programming language f... by recursive on Wednesday August 01, 2018 @11:26AM (#17663343)
Yes, it does. And the result of that exception produces a signed infinity, unless the numerator was zero. Note that this is different than the language-level Error construct that can be thrown and caught.
Re:Grain: A strongly-typed functional programming language f... by thangngoc89 on Tuesday July 31, 2018 @01:54AM (#17650850)
I think the marketing page is not doing a great job. Grain is a language compiled to WebAssembly. So comparing it with either Javascript or Elm is pointless
Re:Grain: A strongly-typed functional programming language f... by masklinn on Tuesday July 31, 2018 @05:51AM (#17651816)
> Grain is a language compiled to WebAssembly. So comparing it with either Javascript or Elm is pointless

This ability is a tool and nothing precludes a wasm target for Elm (in fact Evan specifically expressed interest in it: https://github.com/WebAssembly/gc/pull/1#discussion_r1115011...).

Either way, comparing Grain to JS or Elm is anything but pointless, at the end of the day it's competing with them.

Re:Grain: A strongly-typed functional programming language f... by bad_user on Tuesday July 31, 2018 @08:37AM (#17652643)
If we're speaking of competition and JavaScript, then a much stronger competitor would be PureScript.

http://www.purescript.org/

PureScript is a Haskell dialect that was built specifically to run on top of JavaScript engines. Specifically, compared with Haskell, it is strictly evaluated (whereas Haskell is non-strict / lazy, well almost). However it eliminates some of Haskell's baggage, but retains Haskell's functional purity.

It's all around an awesome programming language for FP that targets JavaScript engines, far surpassing any other attempt.

Re:Grain: A strongly-typed functional programming language f... by tlrobinson on Tuesday July 31, 2018 @02:02AM (#17650884)
> So comparing it with either Javascript or Elm is pointless

Why? They all target browsers. What else would you compare it to?

Re:Grain: A strongly-typed functional programming language f... by thangngoc89 on Tuesday July 31, 2018 @02:06AM (#17650899)
Like comparing to Rust compilation to WebAssembly for example?
Re:Grain: A strongly-typed functional programming language f... by ForHackernews on Tuesday July 31, 2018 @04:52AM (#17651583)
Does Rust have any DOM integration?
Re:Grain: A strongly-typed functional programming language f... by ekidd on Tuesday July 31, 2018 @05:40AM (#17651782)
Yes. For a while, you've been able to embed JavaScript wrappers using stdweb (https://github.com/koute/stdweb). There are pre-built libraries covering much of the DOM. But you may need to submit PRs if you get heavily into <video> or something else with non-standard APIs.

The shiny new toy is wasm-bindgen (https://github.com/rustwasm/wasm-bindgen), which will soon allow the use of WebIDL (https://heycam.github.io/webidl/) to wrap the entire browser API, if I understand correctly.

In practice, it all seems to work pretty well. But for public-facing sites, you need to watch the number of dependencies you include and keep the *.wasm size down.

Re:Grain: A strongly-typed functional programming language f... by masklinn on Tuesday July 31, 2018 @05:49AM (#17651807)
There are vdom/components-based libraries based on that as well e.g. Yew seems popular.
Re:Grain: A strongly-typed functional programming language f... by vijaybritto on Tuesday July 31, 2018 @02:57AM (#17651092)
They've even got the ability to query dom using a light weight lib on the js side. I think this is a more full fledged framework and they should really talk about it. The marketing page is not upto other frameworks imo.
Re:Grain: A strongly-typed functional programming language f... by mcintyre1994 on Tuesday July 31, 2018 @04:54AM (#17651590)
> No runtime exceptions, ever.

I'm curious how they handle JSON parsing. For example in Scala/Play you define the class you want to parse to, and if the JSON passed in at runtime doesn't match the shape of that class then you get a runtime exception. Obviously it'd be nice if that didn't happen, but I can't think of any alternative that would make sense.

Re:Grain: A strongly-typed functional programming language f... by masklinn on Tuesday July 31, 2018 @05:54AM (#17651831)
> Obviously it'd be nice if that didn't happen, but I can't think of any alternative that would make sense.

Returning a sum of success + error, as e.g. Rust's Serde[0] or Elm's Json.Decode[1] do.

The developer gets the feedback that the operation has failed at runtime, but they also get the feedback that the operation can fail and they must handle it somehow at compile-time, even ignoring the issue is an explicit decision.

[0] https://docs.serde.rs/serde_json/de/fn.from_str.html

[1] http://package.elm-lang.org/packages/elm-lang/core/latest/Js...

Re:Grain: A strongly-typed functional programming language f... by bad_user on Tuesday July 31, 2018 @08:41AM (#17652661)
In Scala too well grown libraries return errors via sum types, e.g. Either.

In Play this is actually something like JsSuccess/JsError, not an exception, although Play is pragmatic (aka dirty) at times, so it's possible that it has functions throwing exceptions.

Re:Grain: A strongly-typed functional programming language f... by diaz on Tuesday July 31, 2018 @05:22AM (#17651708)
You should look into other more saner json libraries. It's unacceptable to have a runtime error. Nowadays I recommend circe.
Re:Grain: A strongly-typed functional programming language f... by pure-awesome on Tuesday July 31, 2018 @05:20AM (#17651695)
I could be wrong about this, but I think that, like Elm, it's not technically Grain that throws the runtime exception. It's whatever is reading in the JSON.

In more detail:

It's purely functional, so it cannot handle I/O at all on its own. It needs some sort of harness into which it fits which handles that, and which then calls the pure functions in Elm / Grain. In Elm's case that harness is JavaScript, and it seems to be a similar case for Grain. (Maybe for Grain it's WebAssembly? I don't honestly know enough about Web Dev to say).

During I/O (including user input, and sending data over a network), runtime exceptions can still be thrown, but once it's been converted and passed into the functional part, it's in a sense correctly formatted by definition, and the purely functional Elm / Grain parts don't throw runtime exceptions at all.

Re:Grain: A strongly-typed functional programming language f... by tomp on Tuesday July 31, 2018 @03:52AM (#17651328)
I wonder how they handle array out-of-bounds accesses...
Re:Grain: A strongly-typed functional programming language f... by masklinn on Tuesday July 31, 2018 @05:57AM (#17651843)
Likely like Elm, where indexing into an array returns a Maybe. OOB return Nothing, while in-bound returns Just <value>.

Or they don't support indexing at all.

Re:Grain: A strongly-typed functional programming language f... by dleclere on Tuesday July 31, 2018 @04:17AM (#17651438)
Looks like they're using an indexed Algebraic Data Type.

https://github.com/grain-lang/grain/blob/master/src/grain-st...

Re:Grain: A strongly-typed functional programming language f... by masklinn on Tuesday July 31, 2018 @05:59AM (#17651849)
There's no indexing in that.
Re:Grain: A strongly-typed functional programming language f... by vilu on Tuesday July 31, 2018 @04:05AM (#17651384)
Maybe by making the API of index based list datatypes return the value inside of a container type. In general it's a helpful strategy when creating total functions.
Re:Grain: A strongly-typed functional programming language f... by thefounder on Tuesday July 31, 2018 @03:41AM (#17651279)
I don't think web languages should have comparisons with JS on their homepage now that we have wasm.
Re:Grain: A strongly-typed functional programming language f... by oconnor663 on Tuesday July 31, 2018 @03:47AM (#17651304)
The WASM devs have really been trying to correct the "WASM will replace JS" meme. I don't think any of them believe that it will, or even that it would be a good thing if it did.
Re:Grain: A strongly-typed functional programming language f... by thefounder on Tuesday July 31, 2018 @03:56AM (#17651344)
I wonder how many people actually believed that. People want to use their favorite language on both the server and the client/browser. Why is so hard to get this?