16 ms·
Stupid Languages
- Xion 14y agoThis 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 14y ago"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 14y agowith 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 ...
- deleted 14y ago[deleted]
- jhuni 14y agoOne 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 14y agoor 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 14y agoAlternatively, you could partially apply the entire list to the function.
- Evbn 14y agoHmm? What is the reverse of (partial map constantFunctionReturnsZero)? A fold/reduce is just as sometimes-reversible, when paired with an appropriate unfold. (example: multiplication and factorization) I think you mean that map is self-composable, in the sense that the map function distributes over function-composition, in the same way that (in first-order functions) multiplication distributes over addition.
- jhuni 14y ago> What is the reverse of (partial map constantFunctionReturnsZero)? The function (constantly 0) is implemented as a place in order to maintain reversibility semantics: ((constantly 0) 10) ;-> (0 10) ((constantly 0) 50) ;-> (0 50) The information lost by calling the constant function is pushed to the end of the list so that it can be called reversibly. This can be applied on an entire list: (map (constantly 0) [1 2 3]) ;-> ([0 0 0] [1 2 3]) > A fold/reduce is just as sometimes-reversible The reduce function is not reversible, but the reductions function when called with a group is: (reductions + [1 2 3 4]) ;-> [1 3 6 10] The reduce value is the last element of the list so it can be retrieved by the last place: (last [1 3 6 10]) ;-> (10 [1 3 6]) > I think you mean that map is self-composable The preservation of information is more important to me then composition.
- dkersten 14y agoTo me, the bigger issue is that the unused 3rd argument is silently ignored without error or warning.
- jzwinck 14y agoNot 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.
- ahoge 14y agoThat's how JS works. You can pass as many extra parameters as you want (they get discarded) and you can also omit as many parameters as you want (it's like passing undefined). The array-like `arguments` object will always reflect what was actually passed to the function though.
- jchrisa 14y agoMy favorite thing about JavaScript... must be a matter to personal taste.
- rekwah 14y agoFor another quick 'WAT' talk, see Gary Bernhardt from CodeMash 2012. https://www.destroyallsoftware.com/talks/wat https://www.destroyallsoftware.com/talks/wat
- laureny 14y agoThis 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 14y agoIt 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.
- chimeracoder 14y ago> 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 14y agoSeems 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.
- ricardobeat 14y agoYou mean reduce()? https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/Reduce https://developer.mozilla.org/en-US/docs/JavaScript/Referenc...
- PommeDeTerre 14y agoWhy 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.
- 14y ago
- chimeracoder 14y ago> 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').
- xyproto 14y agoBase 1 does make sense! 0 = 0 00 = 1 000 = 2 0000 = 3 etc
- eggnet 14y agoWhat 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: aB^2 + bB^1 + cB^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 = 11^0 = 1 11 = 11^1 + 11^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 = 01^0 = 0 00 = 01^1 + 01^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 = 11^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 14y agoI had the same reaction as you had, but apparently, OP is correct: https://en.wikipedia.org/wiki/Base_1 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.
- ehsanu1 14y agoYou can represent 0 by absence. : 0 o : 1 oo : 2 ooo: 3 Of course, this is not a practical notation, since 0 would hard to distinguish from actual absence, but it would be viable in some situations: a table of numbers say, where you know that no cells are empty. So theoretically, it is possible to represent 0 in base 1, regardless of its obvious impracticalities.
- NegativeK 14y ago
- politician 14y agoIn 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 14y agoIt'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 14y agoYes, 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 14y agoI'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.
- 14y ago
- ricardobeat 14y agoI 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 14y agoI think in that case it would be better to make it variadic on input arrays, like map(makeInterval, array, array.tail())
- gsg 14y ago> 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 14y agoYou 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 http://news.ycombinator.com/item?id=4783229 (That I apparently won. :P)
- gsg 14y agoI see, people were mistaking the different nature of values in C and Python for a difference in calling semantics.
- d0mine 14y agoYou 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.
- ubernostrum 14y agoThe answer -- regardless of who thinks they can "win" the argument -- is "this is not a useful question to ask, because people will draw incorrect conclusions, based on assumptions from other languages, from whichever answer is given". Similarly, "pointer to something" is not a useful way to think about Python, because people with a background in C will start making assumptions about what "pointer" means. You might think that assigning to that "pointer" changes what's stored in the memory it points to, but really all it does is re-bind a name within the (local, which does not affect global) scope, leaving the "memory" unchanged. So rather than ask which misleading-analogy-to-another-language Python uses, just ask how Python works.