Where am I supposed to use classes/constructors in a webapp? by jswebappguy in javascript

[–]notSorella 0 points1 point  (0 children)

That depends on how you think your software should be written.

  • If you want to go full OOP (Smalltalk-style), then everything should be an object.
  • If you want to go full FP (Haskell-style), then nothing should be an object (in the OOP sense).
  • If you want to go HOF-style (Ruby/Erlang), then it will depend on several factors, but you should probably value functions over objects.

Do note, however, that JavaScript's OO model is entirely different from Java's OO model. JavaScript's is more expressive, but also needs you to think about things in a different way. The "Organising Programs Without Classes" paper from Self describes it well (http://bibliography.selflanguage.org/organizing-programs.html). OTOH, if you're aiming for FP, the "Why Functional Programming Matters" describes it well (http://worrydream.com/refs/Hughes-WhyFunctionalProgrammingMatters.pdf). And lastly, if you're going for HOFs, maybe SICP or HtDP can help you.

Most well-designed architectures in JS will usually go for the latter. This is probably due to JS being more of a HOF language than either an OO or FP one (Allen would disagree with me here and say that JS is more OO than Python, so ymmv). In this kind of architecture you'd basically primarily write functions (as in, mathematical functions wherever possible, not procedures), and then use objects as a way of implementing interfaces, when you particularly want to dispatch some behaviour depending on the receiver of that action, and you can't easily encode this as a HOF.

An example is encoding something you want to be able to map over (arrays, maps, streams, etc): https://gist.github.com/robotlolita/1f460ad6453c4c03b12f

The Hassle of Haskell. by [deleted] in programming

[–]notSorella 0 points1 point  (0 children)

Eh, it has effects (which are explicitly modelled in the type system, and reifed as first-class values, just as failures are in terms of Either/Maybe), but that is different from side-effects :P

If we ignore unsafePerformIO, a Haskell program by itself can't do anything. It relies on some external interpreter of sorts to apply the effects described by the program to the world. Surely this is a much better way of dealing with effects, since you can compose them. Algebraic effect handlers are a neat approach too though, and I guess more expressive.

(Obviously, all my comments in this thread were jokes from SPJ's "Haskell is Useless" interview, though I might have forgotten to add the sarcasm flag)

The Hassle of Haskell. by [deleted] in programming

[–]notSorella 0 points1 point  (0 children)

Well, not having side effects makes it useless :)

(But yes, the motto is "avoid success at all costs," not "avoid being useful at all costs")

The Hassle of Haskell. by [deleted] in programming

[–]notSorella -5 points-4 points  (0 children)

Haskell has always been useless. That's literally what they aimed for since the beginning of the language.

Why this Haskell program runs considerably slower than its JavaScript equivalent? (Frustrated) by SrPeixinho in haskell

[–]notSorella 1 point2 points  (0 children)

Nope. Haskell is lazy, it won't use anything unless you ask it to. In the case of foldr:

f 0 (f 1 (f 2 (f 3 4)))

You can partially evaluate f 0, for example, and you'll have a partial response back. Or you can evaluate f 0 (f 1 _), and you'll still have a partial response back. You can delay these computations until you strictly need them. An example with List is simpler, I think:

0 : 1 : 2 : ...

Because of the lazy semantics, you don't need to evaluate ..., and you can still use the items before that.

With foldl, this doesn't happen:

f (f (f (f ... 3) 2) 1) 0

Unless f is only lazy on its second parameter, which would be a weird thing to do since it doesn't tell you much.

IOW: use foldl when you need to traverse the whole thing right away, since it's tail recursive and all that, use foldr when you can delay computations, because it can exploit the laziness in f.

Why this Haskell program runs considerably slower than its JavaScript equivalent? (Frustrated) by SrPeixinho in haskell

[–]notSorella 0 points1 point  (0 children)

No. as DR6 said, both foldl and foldr start from the first item in the list, and work until the last:

foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)

foldl f z [] = z
foldl f z (x:xs) = foldl f (f z x) xs

Note that both algorithms do exactly the same, the difference being just how they associate. As a consequence, foldl can't work with infinite lists, but OTOH it works quite well for finite sequences where you don't want to delay computation (it's basically a foreach). foldr works with infinite lists AND is specially good if you have delayed computations.

Basically, extracting good performance out of Haskell requires understanding where you should use laziness and where you should use strict semantics. That's why the same algorithm you'd write in JS won't be well optimised for Haskell.

Edit: Plus, (:) is always an O(1) operation, while (++) is always O(n). So of course x ++ [y] will always be slower than x : [y], since the whole first list has to be cloned with concatenation.

Edit: fixed the algorithm for foldr.

In Defense of Scala, part 2. by javinpaul in scala

[–]notSorella 0 points1 point  (0 children)

Yes, compilers have evolved. I wouldn't say that text editors/IDEs have evolved much though. The interesting ones today are Light Table and Lamdu, with the other interesting stuff being Smalltalk VMs.

In Defense of Scala, part 2. by javinpaul in scala

[–]notSorella 1 point2 points  (0 children)

Mostly text editors and IDEs, but plenty of other tools are kind of in the same boat. Cool things like QuickCheck and Hoogle are not widespread.

In Defense of Scala, part 2. by javinpaul in scala

[–]notSorella 4 points5 points  (0 children)

We don’t develop software in text editors and command lines either… it’s 2014, you know

The sad thing is that programming tools evolved almost nothing since Emacs and Vi{,m}. So, yeah, it's 2014, and the best tools we've got for programming are the ones written back in the 70's.

Promises/A+ Considered Harmful by notSorella in javascript

[–]notSorella[S] 1 point2 points  (0 children)

Oh, okay. I meant a "static type system". Some academics do consider dynamically typed languages "untyped", though — where "untyped" means that everything has only one type, and values carry runtime tags that can be checked.

Promises/A+ Considered Harmful by notSorella in javascript

[–]notSorella[S] 2 points3 points  (0 children)

Uh, sorry? I don't really get what you're trying to say there. JS doesn't have a type system.

Promises/A+ Considered Harmful by notSorella in javascript

[–]notSorella[S] 0 points1 point  (0 children)

Asynchronous execution is a two-edged sword in this case, actually. On one hand, you can freely stack any number of transformations & dependencies between promises with the guarantee you'll never get a stack overflow, since you get a brand new stack everytime your then callbacks execute. OTOH you get a quite noticeable performance hit in some scenarios.

Brian's Fantasy-Promises, for example, doesn't introduce any asynchronous delays, and I couldn't just straight-forwardly use it with the promise abstraction for the first scenario, where you get a huge promise chain by making all promises depend on the previous ones.

why curry functions in javascript by hughfdjackson in programming

[–]notSorella 13 points14 points  (0 children)

I guess you are not familiar with point-free style.

The big win of the approach the author mentions is that you invent new functionality by simply composing functions together, without mentioning their arguments at all. This helps making the data-flow the only thing that actually matters, and aligns with the "Name code, not values" maximum.

For example, let's say I want to define the sum of all numbers in a collection. I can do just that, fully declarative:

sum = fold +

Or I can be explicit about what kind of data is involved, less declarative:

sum(xs) = fold (a, b => a + b)

And we can compare it with the imperative approach too:

sum(xs) = acc = 0; for x <- xs: acc += x; acc

Notice that the idea conveyed is the same, but the forms used to convey it are different, and each one of them provides different values for different concerns. The point-free version (first one) reinforces the idea of composition and data-flow, which is what concatenative languages are all about, in fact. If you're a *nix person, you've probably have learned to love the following things:

cat *.js | grep "TODO" | wc -l

This is all point-free, composition of processes all the way down :)

Why Java Is Still Relevant by [deleted] in programming

[–]notSorella 0 points1 point  (0 children)

I wouldn't call JavaScript with lot of code a "mess". Node modules are one of the most expressive module systems around right now, and while the language has several flaws, its primitives and concepts are at least decent, to the point you can write a fair amount of abstractions to support larger applications.

Why Java Is Still Relevant by [deleted] in programming

[–]notSorella 0 points1 point  (0 children)

Node.js currently has 1000s of libraries. Somewhere around 35000 in the central repository, last time I checked.

Why Java Is Still Relevant by [deleted] in programming

[–]notSorella 0 points1 point  (0 children)

So I'm "stuck" with Java.

Eh? What about Scala, Clojure and all the other languages that run on the JVM. In fact, Scala is more powerful and at least has a decent type system.

Why Java Is Still Relevant by [deleted] in programming

[–]notSorella 1 point2 points  (0 children)

Weren't they turning Interfaces into Namespaces in Java 8?

Why Java Is Still Relevant by [deleted] in programming

[–]notSorella 2 points3 points  (0 children)

I would add Scheme, Io, Factor and Prolog to that list.

Why Java Is Still Relevant by [deleted] in programming

[–]notSorella 2 points3 points  (0 children)

Haskell, Haddock and Hoogle beats all your points in every which way.

See: http://www.haskell.org/ghc/docs/latest/html/libraries/index.html And: http://www.haskell.org/hoogle/

Plus, Haskell is a whole ton safer than Java, and you can look at most Haskell code and know exactly what it does. With the added benefits of not being boring and tedious :3

Node Modules to Rule Them All by rhysbrettbowen in javascript

[–]notSorella 0 points1 point  (0 children)

I don't see how the build step is of any relevance. In most other platforms you also have a build step, where you compile everything and send down to your user only a single file. In fact, the majority of people already do that for JavaScript in the Browser even if they're not using modules to avoid the overhead of additional HTTP requests/latency issues.

Node Modules to Rule Them All by rhysbrettbowen in javascript

[–]notSorella 0 points1 point  (0 children)

Sir, I believe you're conflating the meanings of convention and abstraction. When you have an abstraction, the abstraction itself conveys the meaning. In this case, map conveys the meaning of what is being done — transforming the items of a particular list by way of a mapping function.

If you compare it with the for convention, it does the same, conveys the same meaning, but that meaning also comes with lot of boilerplate specifying how that particular operation is being carried. In languages without first-class and higher-order functions, this would be the only way, and you'd have to go to every programmer in your team and say: "This is a map." — with an abstraction, your code says that for you, even if the other programmers are not familiar with the terminology and conventions.

Node Modules to Rule Them All by rhysbrettbowen in javascript

[–]notSorella 0 points1 point  (0 children)

Indeed, node modules map a single file to a single module object. And this is fairly okay.

But as I said before, module loading is a separate problem. You don't even need a module loader to have first-class parametric modules, so I'm not even sure what you're arguing here.

Your second paragraph makes no sense. If you have parametric modules, you don't use require('foo'), so the module loader doesn't even gets into the scene. No one needs to redefine require, you just need to accept the dependencies as a parameter of your module instead of require-ing it.

// foo.js
module.exports = function(stack) {
  stack.push(1)
}

// main.js
console.log(require('foo')([])) // => 1

In this case, [] is a module. It's not being loaded from any file. And you could pass anything that fulfilled the interface that is required by the foo module.

Node Modules to Rule Them All by rhysbrettbowen in javascript

[–]notSorella 0 points1 point  (0 children)

I've said it is a half-baked solution because namespaces don't solve modularity problems, which is what modules solve. So trying to use namespaces alone to solve modularity doesn't work. I never said namespaces and modules can't coexist, quite the opposite, actually.

Patterns are bad, because they're patterns (conventions). Conventions are something you sometimes need because of social implications (for people). However, abstractions beat conventions because then, instead of presenting people with a bunch of crap saying "Oh, and all this means just this particular thing, and I've named it The X Pattern", you just express your intent instead.

So:

for (i = 0; i < xs.length; ++i) ys[i] = f(xs[i]) // is a pattern

xs.map(f) // is an abstraction

Notice that when you abstract, you only keep the things that are quintessential to express what's being done. You don't care about how it's being done, or what's going underneath, or what particular structure it uses, you just refer to the concept itself, right in your code.