tag:blogger.com,1999:blog-10770855.post111890700862953271..comments2024-03-13T03:10:53.745-04:00Comments on The Little Calculist: ClassicJavascriptDave Hermanhttp://www.blogger.com/profile/00405190527081772997noreply@blogger.comBlogger5125tag:blogger.com,1999:blog-10770855.post-69467192252171382092020-07-04T02:05:53.864-04:002020-07-04T02:05:53.864-04:00Coronavirus lockdown continues worldwide, our Quic...Coronavirus lockdown continues worldwide, our QuickBooks experts at <a href="https://local.google.com/place?id=10143105325404146638&use=posts&lpsid=4654670982125557385" rel="nofollow">QuickBooks Enterprise Support Phone Number</a> 1-833-325-0220 still to deliver round the clock assistance. The team of experts solves all kinds of issues & queries with effective solutions. For More: https://g.page/qb-support-number-hawaii?gmThe Qb Payrollhttps://www.blogger.com/profile/01501886900660719710noreply@blogger.comtag:blogger.com,1999:blog-10770855.post-1127895443137510642005-09-28T04:17:00.000-04:002005-09-28T04:17:00.000-04:00http://lists.canonical.org/pipermail/kragen-tol/20...http://lists.canonical.org/pipermail/kragen-tol/2005-September/000792.html<BR/><BR/>I'm responding to the question, "So how do I code up addition, or<BR/>anything where you want to take arguments other than this?", from<BR/>http://calculist.blogspot.com/2005/06/classicjavascript.html --- with<BR/>regard to Abadi and Cardelli's object calculi.<BR/><BR/>This is explained in a slightly different notation than Abadi and<BR/>Cardelli use for their object calculus. I'm leaving out the syntactic<BR/>sugar I usually use in order to keep this explanation simple for those<BR/>who haven't read Abadi and Cardelli.<BR/><BR/> {} is an object with no methods.<BR/><BR/> self.foo = self.bar + 1 is a method whose definition is "call bar<BR/> on the same object, then add 1." Abadi and Cardelli write this as<BR/> "foo = sigma(self) self.bar + 1".<BR/><BR/> x.foo = x.bar + 1 is the same method (or, if you prefer, another<BR/> method that behaves identically.) This expression lexically binds<BR/> the name 'x' within the method definition to the "self" parameter<BR/> --- the object the method is called on.<BR/><BR/> x{ self.foo = self.bar + 1 } is an override expression; it means<BR/> "an object exactly like x, except that it has this new foo<BR/> method," which is defined as above.<BR/><BR/> I'll separate methods inside objects or override expressions with<BR/> newlines or commas.<BR/><BR/> I've also added new methods to objects in override expressions<BR/> without restraint; you can rewrite this code so that it only ever<BR/> overrides existing methods, as in Abadi and Cardelli's work,<BR/> without much effort, simply by adding useless method definitions<BR/> in objects whose descendants do this.<BR/><BR/>So here are booleans:<BR/><BR/>{<BR/> booleans.true = {<BR/> self.negated = booleans.false<BR/> self.ifTrue = { x.then = 1, x.else = 0, x.val = x.then }<BR/> self.ifFalse = self.negated.ifTrue<BR/> }<BR/> booleans.false = booleans.true {<BR/> self.negated = booleans.true<BR/> self.ifTrue = booleans.ifTrue { x.val = x.else }<BR/> }<BR/>}<BR/><BR/>If "hungry" is a variable that might be one of booleans.true or<BR/>booleans.false, we can say<BR/><BR/> hungry.ifTrue{ x.then = "eat", x.else = "don't eat" }.val<BR/><BR/>Suppose hungry is the above 'true'. This resolves to<BR/><BR/> {<BR/> self.negated = booleans.false<BR/> self.ifTrue = { x.then = 1, x.else = 0, x.val = x.then }<BR/> self.ifFalse = self.negated.ifTrue<BR/> }.ifTrue{ x.then = "eat", x.else = "don't eat" }.val<BR/><BR/>and then<BR/><BR/> { <BR/> x.then = 1, x.else = 0, x.val = x.then<BR/> }{ <BR/> x.then = "eat", x.else = "don't eat" <BR/> }.val<BR/><BR/>which reduces to<BR/><BR/> { x.then = "eat", x.else = "don't eat", x.val = x.then }.val<BR/><BR/>Which resolves to 'x.then', with 'x' being the above-constructed<BR/>object whose 'then' is defined as "eat". Supposing instead that<BR/>hungry were 'false'; instead we get<BR/><BR/> booleans.true {<BR/> self.negated = booleans.true<BR/> self.ifTrue = booleans.ifTrue { x.val = x.else }<BR/> }.ifTrue{ x.then = "eat", x.else = "don't eat" }.val<BR/><BR/>If we expand out the booleans.true here, we get<BR/><BR/> {<BR/> self.negated = booleans.false<BR/> self.ifTrue = { x.then = 1, x.else = 0, x.val = x.then }<BR/> self.ifFalse = self.negated.ifTrue<BR/> }{<BR/> self.negated = booleans.true<BR/> self.ifTrue = booleans.ifTrue { x.val = x.else }<BR/> }.ifTrue{ x.then = "eat", x.else = "don't eat" }.val<BR/><BR/>And then if we evaluate the first override expression, we get<BR/><BR/> {<BR/> self.negated = booleans.true<BR/> self.ifTrue = booleans.ifTrue { x.val = x.else }<BR/> self.ifFalse = self.negated.ifTrue<BR/> }.ifTrue{ x.then = "eat", x.else = "don't eat" }.val<BR/><BR/>since the only method from 'true' not overridden in 'false' is<BR/>ifFalse. Now we can evaluate the .ifTrue method call and get:<BR/><BR/> booleans.ifTrue { x.val = x.else }{ x.then = "eat", x.else = "don't eat" }.val<BR/><BR/>which expands out to<BR/><BR/> { <BR/> x.then = 1, x.else = 0, x.val = x.then<BR/> }{ <BR/> x.val = x.else <BR/> }{ <BR/> x.then = "eat", x.else = "don't eat" <BR/> }.val<BR/><BR/>We can collapse the first override and get<BR/><BR/> { <BR/> x.then = 1, x.else = 0, x.val = x.else<BR/> }{ <BR/> x.then = "eat", x.else = "don't eat" <BR/> }.val<BR/><BR/>and then the second, and get<BR/><BR/> { <BR/> x.then = "eat", x.else = "don't eat", x.val = x.else<BR/> }.val<BR/><BR/>And that reduces to just 'x.else', which is defined as "don't eat".<BR/>This is exactly the same as the last reduction step for when hungry<BR/>was 'true', except that we inherited a different definition for<BR/>'x.val'.<BR/><BR/>Now, for numbers. A real implementation of this object-calculus on a<BR/>computer would use the CPU's rapid number-handling machinery rather<BR/>than implementing its own math primitives, and the method I am about<BR/>to explain is a terribly inefficient way of implementing them anyway;<BR/>its purpose is to demonstrate that the object-calculus can<BR/>theoretically perform any computable computation on its own. The<BR/>following technique is just a transliteration of the lambda-calculus's<BR/>Church numerals.<BR/><BR/>Here's an object containing numeric primitives; I assume the earlier<BR/>booleans object is available under the name 'booleans'.<BR/><BR/>{<BR/> numbers.zero = {<BR/> self.isZero = booleans.true<BR/> self.plus = numbers.sum { x.firstArgument = self }<BR/> self.succ = self { <BR/> succ.isZero = booleans.false<BR/> succ.pred = self <BR/> }<BR/> }<BR/> numbers.lessThan = {<BR/> self.firstArgument = numbers.zero<BR/> self.secondArgument = numbers.zero.succ<BR/> self.val = self.secondArgument.isZero.ifTrue {<BR/> x.then = booleans.false<BR/> x.else = self.firstArgument.isZero.ifTrue {<BR/> x.then = booleans.true<BR/> x.else = numbers.lessThan {<BR/> child.firstArgument = self.firstArgument.pred<BR/> child.secondArgument = self.secondArgument.pred<BR/> }.val<BR/> }.val<BR/> }.val<BR/> }<BR/> numbers.sum = {<BR/> self.firstArgument = numbers.zero.succ<BR/> self.secondArgument = numbers.zero.succ<BR/> self.val = self.firstArgument.isZero.ifTrue {<BR/> x.then = self.secondArgument<BR/> x.else = self {<BR/> child.firstArgument = self.firstArgument.pred<BR/> }.val.succ<BR/> }.val<BR/> }<BR/>}<BR/><BR/>The above definitions should evaluate <BR/><BR/> numbers.zero.succ.succ.succ.plus { <BR/> x.secondArgument = numbers.zero.succ.succ.succ.succ<BR/> }.val<BR/><BR/>to the same thing as numbers.zero.succ.succ.succ.succ.succ.succ.succ.<BR/>But I may have made a mistake.<BR/><BR/>So the short answer is that methods often return an object not derived<BR/>from self, but some of whose method definitions are closed over self.<BR/><BR/>As I've implied previously (in "functional programming for amateurs in<BR/>an outliner", before I read Abadi and Cardelli's book --- thank you<BR/>David Gibson!) I think this is the theoretical underpinning for<BR/>dramatically more usable and productive programming environments.<BR/><BR/>Links:<BR/><BR/>> Abadi and Cardelli's object calculus is described in the first three<BR/> pages of "A Theory of Primitive Objects" at<BR/> http://research.microsoft.com/Users/luca/Papers/PrimObj1stOrder.pdf<BR/>> "functional programming for amateurs in an outliner" is at<BR/> http://lists.canonical.org/pipermail/kragen-tol/2002-May/000713.html<BR/>> "towards a modern programming environment" is at<BR/> http://lists.canonical.org/pipermail/kragen-tol/2003-May/000745.html<BR/>> Also related is Jonathan Edwards' Subtext:<BR/> http://subtextual.org/<BR/>> And Wouter van Oortmerssen wants "abstractionless programming", the <BR/> same thing:<BR/> http://lambda-the-ultimate.org/node/view/17<BR/>> And Dynamic Aspects' "domain/object" platform seems to be a larger <BR/> idea including the same kernel:<BR/> http://www.dynamicaspects.com/Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-10770855.post-1118980752216097112005-06-16T23:59:00.000-04:002005-06-16T23:59:00.000-04:00If you aren't already aware of them, there are som...If you aren't already aware of them, there are some really neat <A HREF="http://citeseer.ist.psu.edu/304252.html" REL="nofollow">object calculi</A> where extension-via-protoyping and method reference is <B>all</B> you have. And when I say "all", its significant, because all the methods take only one argument, which is (wait for it) <I>this</I>. That's it, no extra arguments.<BR/><BR/>So how do I code up addition, or anything where you want to take arguments other than this? Yeah, I puzzled over that one too. Its pretty cool stuff.<BR/><BR/>(I don't know that much about it; <A HREF="http://ccedevdiary.blogspot.com" REL="nofollow">Carl</A> is the expert on this stuff at the moment.)pnkfelixhttps://www.blogger.com/profile/04222189622973190255noreply@blogger.comtag:blogger.com,1999:blog-10770855.post-1118927574131500532005-06-16T09:12:00.000-04:002005-06-16T09:12:00.000-04:00I'm retarded Dave, sorry, disregard my other comme...I'm retarded Dave, sorry, disregard my other comment...Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-10770855.post-1118920091678438822005-06-16T07:08:00.000-04:002005-06-16T07:08:00.000-04:00Maybe your semantics capture this, but consider th...Maybe your semantics capture this, but consider this stupid accumulator:<BR/><BR/>var j = 1;<BR/>function accum() {<BR/> var n = 1;<BR/> function inc() {return j*n++;}<BR/> return inc;<BR/>}<BR/><BR/>j isn't put in inc's closure, n is, but wouldn't your MakeClosure rule put j in the closure for inc? I'm probably missing something. It's <A HREF="http://www.jeffpalm.com/dave.html" REL="nofollow">here</A>, too.Anonymousnoreply@blogger.com