
Stupid Languages - decklin
http://nedbatchelder.com/blog/201301/stupid_languages.html
======
politician
In JavaScript, every function is varadic. The problem is one of contract, not
language. Passing varadic functions to higher-order functions without checking
whether the types are compatible will cause a problem in _every such
language_.

The problem is parseInt, not map. Consider:

    
    
       // using lodash.js (http://lodash.com/)
       
       _.mixin({ args: function () { return _.toArray(arguments); } })
      
       ['10','10','10','10'].map(_.compose(parseInt, _.first, _.args)); // #=> [10,10,10,10]

~~~
ricardobeat
It's nice to use functional concepts and all, but in practice a simple
anonymous function to trim the arguments is clearer and close to zero
overhead:

    
    
        ['10','10','10','10'].map(function(n){ return parseInt(n, 10) })
    

That's one reason to like the conciseness of CoffeeScript, takes the urge to
build compositional towers away:

    
    
        ['10','10','10','10'].map (n) -> parseInt(n, 10)
    

Which one would you rather find in your codebase?

~~~
politician
Yes, you can use anonymous functions, and you probably would want to do that
in practice. However, I was trying to illustrate the point that JavaScript
functions are varadic and function composition was an easy way to drive that
point home.

EDIT: Also, you raise a really good point in your example which is that when
using parseInt you should always specify the base. If I were to modify my
example to take that into account it'd get more messy.

~~~
ricardobeat
I've been using a pair of functions applyRight/Left that fit this case nicely:

    
    
         ['10','10','10','10'].map(applyRight(null, parseInt, [10], 1)
    

The signature is [context, fn, args, slice] where `slice` is the length of
arguments to keep from invocation. It's very rare that something warrants
using it vs an anonymous function though.

~~~
politician
That's interesting, I like how `slice` lets you concat sequences of arguments,
but worry about building functions which have too many convenience features.
Thought experiment: what if I wanted to pass every other argument?

~~~
bdr
Here's what I use:

    
    
      # Adapted from http://autotelicum.github.com/Smooth-CoffeeScript/literate/partial.html
      F.partial = (func, a...) -> (b...) ->
        func (for arg in a then arg ?= b.shift())..., b...
    

For example, do `parseInt10 = F.partial(parseInt, undefined, 10)`, then
`[].map(parseInt10)` does the right thing.

------
chimeracoder
> But it can do things the other maps can't easily, like create an array of
> differences between elements, or a running total, and so on. Other languages
> have other solutions to those problems.

Lisp has some rather elegant solutions to both of those use cases. It's
misleading to say that Javascript's 'map' is more powerful just because it
tries to cram two or three distinct use cases into one.

It's not like Javascript even uses the Lisp definition of 'map' (which is
_not_ what most languages use for map - they use Lisp's 'mapcar').

~~~
efnx
Seems like they included extra parameters in map since they forgot to include
a fold! Running totals are perfect for fold, for differences, use zipWith.

But, JavaScript is rather functional. I've heard it described as "lisp in C's
clothing". Douglas Crockford uses monads in JS (intentionally) and gave an
interesting yet hard to follow introduction to JS monads not too long ago. I'd
like to see the functional side of JS emphasized in the next iteration.

~~~
PommeDeTerre
Why do people keep incorrectly insisting that JavaScript is "functional" or
"Scheme-like"? It is neither.

Merely having anonymous functions does not make a language "functional".
JavaScript does not encourage the use of pure functions. It does not encourage
the use of recursion. It does not encourage immutability. It does not have a
robust, sensible type system. It does not encourage currying.

It's pretty clear that JavaScript is inherently not a functional programming
language. It goes against functional programming techniques in almost all
respects, especially when it comes to JavaScript code that's out in the wild.

~~~
pcwalton
"JavaScript does not encourage the use of pure functions."

Neither does Lisp.

"It does not encourage the use of recursion."

Neither does Lisp. (Common Lisp has no tail recursion in the spec.)

"It does not encourage immutability."

Neither does Lisp. (Actually, ES5 does have pretty powerful primitives for
immutability, Object.freeze for example.)

"It does not have a robust, sensible type system."

If you mean static typing, neither does Lisp.

"It does not encourage currying."

Neither does Lisp.

~~~
ankurdhama
sensible type system means you cannot add string and numbers.

------
Xion
This example clearly violates the principle of least surprise, but it doesn't
necessarily mean that the language it comes from is bad. Rather, the _code_
it's used in is.

~~~
lmm
"map" is sufficiently common and standard that it's a bad name for this
function, irrespective of whether this is a good or bad function to include in
the base language.

~~~
camus
with the new ES6 coming , people from python are going to feel a lot of
confusion , since some new functionalities are inspired by python but are in
reality different from the python implementation,like modules , generators ,
... Javascript has always been like that ( thinking of "this" that is totally
different from "this" of Java for instance , let's not even talk about the new
class keywork which will be very confusing too , for those who believe they
can just go the java way with js from now on ). But i'm quite happy with the
language ,it feels like self, the revenge ...

------
laureny
This is more of a case of a stupid library than stupid language.

And whether it's a stupid library is even debatable. map() has gained a more
popular understanding from functional programming these days but it was
probably not so when this Javascript map() function was added.

~~~
fauigerzigerk
It is very likely that the person who added map() to JavaScript knew about its
meaning in functional languages, otherwise s/he would have called it
applyToEach() or something like that.

------
jhuni
One important characteristic of the map function is that it can be used
reversibly. For example, (partial map inc) is inverted by (partial map dec).
If I want to map over a collection by a function that takes the entire
collection as an argument I'd rather use some function other then map to avoid
confusion.

~~~
justincormack
or just call a closure bound to the whole list. I think I would write the
thing as a for loop though, it feels so un map like

~~~
jhuni
Alternatively, you could partially apply the entire list to the function.

------
dkersten
To me, the bigger issue is that the unused 3rd argument is silently ignored
without error or warning.

~~~
jzwinck
Not at all. Some other languages work this way, and in the right context
(best-effort systems, not mission critical ones), it can be a boon to backward
compatibility and other ease of use factors.

In Python for example you can explicitly declare variadic functions to ignore
extra arguments. But when it's the default behavior you can for example change
the official signature of a callback interface without breaking compatibility.
It can be pretty liberating to work in a best-effort language...though perhaps
it makes testing a bit more important.

~~~
Evbn
Taking this reasoning to its absurd conclusion, why have signatures at all?
Every function could just have an implicit args array.

~~~
jfb
Hello from Perl!

------
gsg
> They want to know if function arguments are call by value or call by
> reference (neither).

My knowledge of Python is limited, but I was under the impression that it is
call by value just like everything else (where Python's notion of value is
"pointer to something"). Am I missing something?

~~~
Jach
You have it right in that it's call by value. But HN already had a fight over
that a while ago: <http://news.ycombinator.com/item?id=4783229> (That I
apparently won. :P)

~~~
d0mine
You essentially changed the definition of "value" to mean what is just called
"name" in Python.

Names refer to objects. Names are introduced by name binding operations such
as `=`, `import`, `def`.

    
    
      def f(a, b):  # a, b - local variables
           a = [1]  # doesn't change  x list; a refers to the new list hence forth
           b.append(2)  # change y list; b refers to the same list as y
    
      x, y = [], []
      f(x, y)
      print x, y  # [], [2]
    

Note: a "win" doesn't change the truth. It just means that nobody cared enough
to participate further in the hostile discussion.

------
ricardobeat
I think one of the reasons for the third argument (the array itself) is to
permit chaining. Consider this:

    
    
        var publishedPosts = posts.filter(function(post){
            return post.published
        })
    
        var intervals = publishedPosts.map(function(post, i){
            var next = publishedPosts[i+1]
            return post.date - (next && next.date || 0)
        })
    

With the array reference you don't need an intermediate var:

    
    
        var intervals = posts.filter(function(post){
            return post.published
        }).map(function(post, i, arr){
            var next = arr[i+1]
            return post.date - (next && next.date || 0)
        })

~~~
krickle
I think in that case it would be better to make it variadic on input arrays,
like map(makeInterval, array, array.tail())

------
rekwah
For another quick 'WAT' talk, see Gary Bernhardt from CodeMash 2012.

<https://www.destroyallsoftware.com/talks/wat>

------
xyproto
Base 1 does make sense!

0 = 0

00 = 1

000 = 2

0000 = 3

etc

~~~
eggnet
What you've done is define your own number system, I do not believe you are
representing what "base 1" might be.

If a base means, you can write numbers of this form:

abc

Where the value is:

a _B^2 + b_ B^1 + c _B^0

and you can only have B symbols, then your one symbol for base 1 would need to
be 1, still useless, but not completely:

1 = 1_1^0 = 1 11 = 1 _1^1 + 1_ 1^0 = 2 ...

Note that you cannot represent 0 in base 1 with this method.

If you choose 0 as your one symbol for base 1, then the only number you can
represent is 0. I assert this is even more useless than selecting 1 as the
symbol.

0 = 0 _1^0 = 0 00 = 0_ 1^1 + 0 _1^0 = 0 ...

As far as I can tell, the example was trying to interpret "10" as base 1. 10
has two different symbols which truly does not make sense in base 1.

I assert that base 1 is not a valid base, because you cannot represent all
integers in it.

Additionally, the "unary point" or whatever it would be called, would serve no
purpose:

1.1 = 1_1^0 + 1*1^-1 = 2

I'm not sure how that might disqualify something for a "base" but it certainly
doesn't help :) Probably the strongest argument is the inability to represent
0.

~~~
ced
I had the same reaction as you had, but apparently, OP is correct:

<https://en.wikipedia.org/wiki/Base_1>

though you are right that it's not the same as base N, N>1\. Also, Wikipedia
uses |||| to represent 4 instead of 0000. It makes more sense.

