6 ms·
Can your programming language do this?
- icey 17y agoIIRC this will also work with PLT Scheme and (I think) Common Lisp (I can't remember if you can use unicode names in CL).
- arb 17y agoYou can. For instance, SBCL introduced support for it around version 0.8 or so (years ago).
- mitko 17y agoYes, it can. All programing languages are equivalent in power, as you can write interpreter of language A in language B for, I think, any two programming languages A and B. However, some languages will achieve some things much easier. Your language apparently makes it pretty easy to create new functions such as sum or product.
- bogdank 17y agoAPL was capable of doing something similar. It would be nice to have keyboards with extended set of characters.
- buugs 17y agoI don't know if it will be of much use but take a look at http://www.jsoftware.com/ http://www.jsoftware.com/ it is similar to apl in style
- gchpaco 17y agoJ took one of APL's chief positives, the only thing that made it possible to look at absurdly dense APL code and make sense of it, and destroyed it. APL has a "one character == one primitive" relation, except for user symbols which all have to be letters. So no matter what jumble of crap you had, you could tokenize it easily starting from anywhere. J has variable length characters.
- slackenerny 17y agojumble of crap you had, you could tokenize it I don't grok this argument, when would one like to have that? For me personally J is all about tacit functional programming. Any APL have this?
- gchpaco 17y agoPut another way, if you see sigma in an APL program, you can understand what that is without knowing its context. Single characters in J do not have this property; < is different from <. is different from <: (and sometimes surprisingly different; =. defines a local and =: defines a global), and in a lot of fonts it's not hard to mistake one for the other. J, to me, took the worst features of APL (the profusion of symbols that only loosely resemble anything else you've ever seen) and makes it even worse, because at least the APL symbols were (usually) visually distinct! From the J examples page are gems like this var =: ~.@(] , |:&.> , |.&.> , |."1&.>)^:3 which in the proportional font they use makes for a real entertaining time telling , from ,. from ..
- silentbicycle 17y agoAs is k. (http://kx.com/ http://kx.com/)
- Sharlin 17y agoWell, I certainly prefer it spelled "sum" -- trivial to understand and viewable with any font. In idiomatic Python, with only basic language features needed: -sum(p(x) * log(p(x)) for x in l)
- deleted 17y ago[deleted]
- brent 17y agoIn matlab: -sum(p(x).*log(p(x))) Both look much cleaner imo.
- DanielStraight 17y agoYes. Why should something which is NOT written in prefix notation in math be written in prefix notation in code? What is so impressive about that? All of my programming languages (who has just one?) can define nice looking functions. None of them use obscure prefix notation, and I think that's a good thing.
- eru 17y agoWhat's so obscure about prefix notation? Having to deal with state and order of computation is a much bigger headache when converting from math to code than fixity.
- silentbicycle 17y agoFor all the talk of how Lisp is so well suited to making minilanguages for expressing things own their own terms, the lack of infix arithmetic seems particularly jarring. I think that infix (Lisps), postfix (Forth), or all-left OR all-right associative (as in Smalltalk and J, respectively) are better choices than infix with order-of-operations (which is just historical cruft, IMHO), but making basic arithmetic awkward is an easy way to give people a bad first impression of a language. In OCaml, which has order-of-operations arithmetic syntax, people instead get mad because it uses different ops (*. +. etc) for floating point math. You can't win.
- ulvund 17y agoR: entropy <- function(x) -sum(p(x)*log(p(x)))
- tedunangst 17y ago"Having a language that lets you declare constructs that look very similar to their mathematical definition is a huge win for readability." I'd agree, except every mathematical definition I've seen used infix notation. Minus a function for summing a series, the C version at least keeps the symbols in the same order. Anyone with even a passing familiarity of C can read this and recognize it as the same thing. double entropy(int x) { double e = 0.0; for (int i = 0; i < x; i++) e += p(i) * log(p(i)); return -e; }
- judofyr 17y agoWorks nicely in Ruby 1.9: #!/usr/bin/ruby -Ku # encoding: utf-8 module Enumerable def sum inject { |acc, val| acc + val } end def Σ(&blk) map(&blk).sum end def entropy(&prob) - Σ { |i| prob[i] * Math.log(prob[i]) } end end EDIT: And in 1.8 if you pass -Ku.
- jrockway 17y agoThis also works fine in Perl, Common Lisp, and Haskell... and probably every other programming language that was designed after 1970.
- pg 17y agoYes, and in fewer tokens: (def entropy (x) (- (sum [* (p _) (log:p _)] x))) I like macros, but I wouldn't use them in this case. Summing is close enough to mapping that the form above is easy for any Lisp programmer to understand. I'd also argue that code size is a more meaningful measure of readability than familiarity. There's nothing intrinsically right about sigma notation. Some people are just more used to it. But since whatever notation you put in a language will eventually become familiar to its users, you should factor out familiarity when making design decisions, or at most use it to break ties. The notation above is honestly more readable to me, because it's what I'm used to.
- deleted 17y ago[deleted]
- arohner 17y agoI'm honored you read my post and replied to it. > I'd also argue that code size is a more meaningful measure of readability than familiarity ... but since whatever notation you put in a language will eventually become familiar to its users, you should factor out familiarity when making design decisions An exaggerated, uncharitable interpretation of what you said would be "users will figure out the notation, regardless of how hard it is, so make them jump through hoops so you can get a shorter notation". How do you distinguish between shorter notation that is a net win, and shorter notation that looks like perl? My goal in using the macro was to reduce noise. Without the macro, the equivalent clojure would look like (defn entropy [x] (- (Σ #(* (p %) (log (p %)) x)) To me, the original version is easier to read because it lacks the #, % characters. Given that every call to sum would likely use an anonymous function (and therefore use #, %), it seemed worthwhile. Maybe that's an argument against clojure, but the arc version is almost as noisy, IMO.
- jrockway 17y agoIf you can write something as a function, that's always a better option than making it a macro. It's clear to any clojure programmer what your entropy function does, just like it's clear to any Perl programmer what all that "line noise" is. (Arguably, there isn't much line noise in Perl, only in regular expressions, which every other language has stolen Perl's implementation of. If you want real line noise regexps, try Emacs Lisp without "rx".)
- jf 17y agoThis reminds me of the Fortress programming language: http://research.sun.com/projects/plrg/Publications/fortress.1.0.pdf http://research.sun.com/projects/plrg/Publications/fortress.... (Image from the part of the above PDF that I was thinking of: http://skitch.com/joelf/bs99c/sun-research-fortress http://skitch.com/joelf/bs99c/sun-research-fortress)
- TweedHeads 17y agoJavascript can do it all: function entropy(x){ return sum(p(x)*log(p(x))); }
- amix 17y agoI am looking forward for Fortress 1), which takes these ideas to the extreme (basically, the whole language is unicoded and the syntax is mathematical). Fortress also features some very innovative features such as implicit parallelism for a imperative language and transactions. One of the creators of Fortress is Guy Steele (one of the guys behind Scheme, Lisp and Java). 1) http://projectfortress.sun.com/Projects/Community http://projectfortress.sun.com/Projects/Community
- keefe 17y agoI don't think the readability of implementations is all that important. Java is widely regarded as having poor syntax, but any client of this type of a method (assuming it is in a static utility class) will do something like double myEntropy = InformationTheory.entropy(myseries); The details of a method like that just aren't all that interesting, it's 10 lines or 200 (likely the latter as there seems to be an optimized version for doing anything). I like to abstract away mathematically complex(ish) things like this and leave syntax like I stated above in my code, so that my code tells a story that is easy to read about how data is being manipulated and really focus on the high level semantics of what is going on. Maybe I am influenced from having done clerical work in HS and typing fast enough that a few lines doesn't matter, but sometimes I prefer longer code, with more interfaces and more abstraction and more standardization to concise and elegant but more obscure approaches.
- trezor 17y agoC#: Func<List<double>, double> entropy = (X) => { double e = 0; X.ForEach((p) => e += p * Math.Log(p)); return -e; }; Compiler gets negative points for not being willing to infer the type-definition of the function-variable though. I guess that is stuff you have to live with in statically typed languages ;) Edit: Just checked. C# allows unicode characters like Σ for functions and variables, although I would never use it myself.
- deleted 17y ago[deleted]
- snprbob86 17y agoNot sure why you are using lambda syntax instead of defining a method shrug, but anyway I don't think the type inference shortcoming is inherent to static typing. See this similar post regarding type inference on fields: http://blogs.msdn.com/ericlippert/archive/2009/01/26/why-no-var-on-fields.aspx http://blogs.msdn.com/ericlippert/archive/2009/01/26/why-no-... I'm sure there is an equally reasonable explanation of costs and implications for your example. Eric Lippert would probably be happy to share it with you, why not ask him? :-)
- scott_s 17y agoYou're right, statically typed languages can use type inferencing; both Haskell and Ocaml do.
- trezor 17y agoI'm sure there is an equally reasonable explanation of costs and implications for your example. There sure is. Had I defined a method (like you suggested), and just gone ahead and made my function variable point to that, the compiler would have enough information to infer types. In that case I would get away with the following: var someFunction = (X) => entropy(X); Just felt like contributing somethings which isn't on the HN daily list of languages, that's all :)
- profquail 17y agoOr you could just do this: double entropy = -1.0d * mydata.Select(x => x * Math.Log10(x)).Sum(); Where 'mydata' is of type IEnumerable<double>.
- jrockway 17y agoYes, my programming language can do that.
- Tichy 17y agoBut how do you type the Σ? Don't do stuff like that... In one project I had to use a templating language that used "<<" as a single character (I still can't type it) instead of <% %> like all the other languages in the world. I ended up using copy and paste for that character whenever I had to edit the templates. Needless to say I enjoyed that project tremendously. Really don't do that - try to stick to ASCII in the source code please.
- gruseom 17y agoBut how do you type the Σ? You simply define a keyboard shortcut. For very common primitives, a special character can work nicely. We use λ in our Common Lisp code instead of typing lambda. Actually, our λ is a macro that does a couple of things besides expanding into lambda; if it were just the latter we probably wouldn't have gone there. Once we did, though, I was surprised at the improvement in readability.
- Tichy 17y agoInteresting. But I hope you put something in the comments of your code on how to create that keyboard shortcut and the unicode for λ.
- jasonkester 17y agoUgh. If anybody ever has to maintain your code, they'll copy/paste the symbol like Tichy described while cursing your name. Personally, I'd copy/paste it into the global find/replace dialog the first time I came across it. I mean, sure, if it was my job to deal with your unicode code every day from here on out, I'd bother to learn how to map screwy symbols to keyboard shortcuts. But really, why would you do this to your code in the first place? It certainly doesn't make things more readable. Exactly the opposite.
- gruseom 17y agoPersonally, I'd copy/paste it into the global find/replace dialog the first time I came across it. Without bothering to understand why it was done that way or discussing it with the team? That wouldn't be a good way to last very long. why would you do this to your code in the first place? I was careful to include a phrase which explains this: for very common primitives. Perhaps your code doesn't have those; ours does. It certainly doesn't make things more readable. Considering that I just finished saying it did, that's quite the claim. screwy symbols Most programmers I've observed are closed-minded about deviations from their comfort zone. Faced with something that doesn't conform to the way they always do things (a.k.a. the Right Way), they reflexively condemn. Your comment is remarkable insofar as every single one of its sentences suggests this mentality. I hope that's just my mistaken impression.
- slava_pestov 17y agoHere's a point-free version in Factor. It looks a bit different from the original formula but once you get used to it its very quick to read; I prefer it to the Lisp code since there are fewer parentheses to track: : entropy ( n -- e ) [1,b] [ p dup log * ] sigma neg ; Note that [1,b] is a word which makes a numeric range from an integer on the stack, and [ ... ] is a function object (quotation).
- gregwebs 17y agohaskell list comprehension entropy x = - sum [p i * (log . p) i | i <- [1..x]]
- hs 17y agoyes, lisp can make certain math simpler consider bounds on a: 0 < a < 1; it's (and (< 0 a 1) (foo)) ... should be easy in any language how about 0 < a < b < 1 ? it's (and (< 0 a b 1) (bar)) ... a little ugly in other languages 0 < a < b < ... < z < 1 ? i won't program that in other languages :p