<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1440405560330732771</id><updated>2026-08-09T01:07:03.712-07:00</updated><category term="parallel browser"/><category term="socio-plt"/><category term="security"/><category term="superconductor"/><category term="synthesis"/><category term="JavaScript"/><category term="flapjax"/><category term="Berkeley"/><category term="ECMAScript"/><category term="multicore"/><category term="programming language theory"/><category term="programming languages"/><category term="TA"/><category term="big data visualization"/><category term="work stealing"/><category term="BayFP"/><category term="CFL-Reachability"/><category term="CouchDB"/><category term="Erlang"/><category term="ErlyWeb"/><category term="Java"/><category term="Parallel FRP"/><category term="Points-To Analysis"/><category term="Prolog"/><category term="Rhino"/><category term="WBRU"/><category term="autotuning"/><category term="bay area"/><category term="cognitive science"/><category term="compilers"/><category term="computer science"/><category term="concolic testing"/><category term="cs164"/><category term="e-cash"/><category term="firefox"/><category term="functional reactive programming"/><category term="garbage collection"/><category term="json"/><category term="lambda calculus"/><category term="machine learning"/><category term="mobile computing"/><category term="optimistic replication"/><category term="power law"/><category term="programming"/><category term="programming language adoption"/><category term="refinement types"/><category term="sk combinators"/><category term="software engineering"/><category term="startup"/><category term="usability"/><category term="web frameworks"/><category term="web worker"/><category term="windows sucks"/><title type='text'>The Good Soldier LMeyerov</title><subtitle type='html'>&lt;b&gt;@LMeyerov: Scientist-at-large launching a big data visualization startup.&lt;/b&gt;&#xa;&lt;br&gt;&lt;br&gt;&#xa;Previous life in hacking new languages: Superconductor for hardware accelerated data visualization, Ph.D. at Berkeley on  multicore web browsers, Flapjax for reactive JavaScript (FRP), and ConScript+Margrave for secure scripting.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default?alt=atom&amp;redirect=false'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default?alt=atom&amp;start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>184</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-4448531873537630142</id><published>2013-12-02T21:24:00.003-08:00</published><updated>2013-12-03T00:39:03.629-08:00</updated><title type='text'>Scaling the Data Wall: Exporting Your List of Kindle Books from Amazon</title><content type='html'>I&#39;m waiting to make a couple of cool announcements about our big data visualization startup. Meanwhile, I wanted to relate a stupid hack I needed to do before I could analyze my reading preferences: a way to download my list of Kindle books from Amazon. Amazon lets you export the list of physical purchases, but they try to only show a few digital purchases at a time. I have hundreds of books, so that&#39;s a no go. Searching on Google showed others got stuck on &amp;nbsp;&lt;a href=&quot;http://www.amazon.com/forum/kindle%20active%20content?_encoding=UTF8&amp;amp;cdForum=Fx3NHHKKZWSWCBP&amp;amp;cdThread=Tx2E65PJ7SY03Z&quot;&gt;Amazon&lt;/a&gt;&amp;nbsp; and &amp;nbsp;&lt;a href=&quot;https://www.goodreads.com/topic/show/1469395-can-u-export-a-list-of-your-purchased-books&quot;&gt;Goodreads&lt;/a&gt; as well. After some dead ends (examining receipt pages, digging around files in their native app, ...), I found a winner.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Long story short, here&#39;s how to extract your reading list from Amazon (~2 min) and, optionally, transform it into a CSV file (~2 min):&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h2&gt;
Extract the List of Books&lt;/h2&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;Log in to your Amazon account&lt;/li&gt;
&lt;li&gt;Click on &quot;Your Account&quot; up top&lt;/li&gt;
&lt;li&gt;Click on &quot;Your Collection&quot; as part of the &quot;Digital Content&quot; box&lt;br /&gt;&lt;br /&gt;You&#39;ll get to a page that&#39;s close but no cigar: books show up as you scroll, but at the same time, old ones get swapped out.&lt;br /&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Hit the print button and wait. And wait. And wait...&lt;/li&gt;
&lt;li&gt;At some point, everything will load. If a printer dialog pops up, cancel it.&lt;/li&gt;
&lt;li&gt;Voila!&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;div&gt;
You can copy/paste the page into a text editor like Notepad and you&#39;ll get a list of records like:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Your Collection&lt;br /&gt;&lt;br /&gt;Title: Diffusion of Innovations, 5th Edition&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Author: Everett M. Rogers&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Date Acquired:&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;January 26, 2010&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Rating:&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Title: Guns, Germs, and Steel: The Fates of Human Societies&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Author: Jared Diamond&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Date Acquired:&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;January 24, 2010&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Rating:&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Don&#39;t use something like Word because it&#39;ll probably copy the HTML structure behind the page.&lt;/div&gt;
&lt;h2&gt;
Transform Into CSV&lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
Most text editors support regular expressions for fixing up content. For whatever search/replace menu item you have, do the following three steps to turn it into a CSV:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;Clean your data by removing commas&lt;br /&gt;Find: &amp;nbsp;&lt;span style=&quot;background-color: #f4cccc; color: red;&quot;&gt;,&lt;/span&gt;&lt;br /&gt;Replace:&lt;/li&gt;
&lt;li&gt;Order your data by making each entry a comma delimited line&lt;br /&gt;Find:&amp;nbsp;&lt;span style=&quot;background-color: #f4cccc; color: red;&quot;&gt;\r(Title|Author|Date Acquired|Rating):&lt;/span&gt;&lt;br /&gt;Replace: &lt;span style=&quot;background-color: #f4cccc; color: red;&quot;&gt;,&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Clean your data by removing all those &quot;Your Collection&quot; lines&lt;br /&gt;Find:&amp;nbsp;&lt;span style=&quot;background-color: #f4cccc; color: red;&quot;&gt;\rYour Collection&lt;/span&gt;&lt;br /&gt;Replace:&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The rewrites will turn the above entries into just two lines&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;, Diffusion of Innovations, 5th Edition, Everett M. Rogers,January 26, 2010,&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;, Guns, Germs, and Steel: The Fates of Human Societies, Jared Diamond,January 24, 2010,&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Success! You have scaled the data wall and can plug in your personal preferences to Excel, Goodreads, or your own homebrew algorithm. Let&#39;s see how long it takes before Amazon plugs this hole!&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/4448531873537630142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/4448531873537630142' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/4448531873537630142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/4448531873537630142'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2013/12/scaling-data-wall-exporting-your-list.html' title='Scaling the Data Wall: Exporting Your List of Kindle Books from Amazon'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-7781378948983370348</id><published>2013-09-14T00:14:00.000-07:00</published><updated>2013-09-14T00:14:09.525-07:00</updated><title type='text'>Sneak Peek for My Strange Loop Talk on Parallel Program Synthesis</title><content type='html'>I&#39;m excited for Strange Loop (&lt;a href=&quot;https://thestrangeloop.com/sessions/software-for-programming-cells&quot;&gt;programmable bio&lt;/a&gt;!) and Emerging Languages Camp next week. My talk will &lt;a href=&quot;https://thestrangeloop.com/sessions/thinking-dsls-for-massive-visualization&quot;&gt;geek out on the language design idea in Superconductor&lt;/a&gt; that makes parallel programming in it such a breeze: program synthesis!&lt;br /&gt;
&lt;br /&gt;
To give a taste, this post takes a synthesis approach to programming regular expressions. The trigger for it was one of the most important issues for programming languages in the 21st century: increasing literacy. My geneticist friend was struggling to transform values in a huge spreadsheet, and telling her to learn regular expressions is a non-starter.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Uphill Both Ways.&lt;/h3&gt;
Imagine a &quot;quick&quot; sed script to rewrite &quot;Alonzo Church&quot; into &quot;C., A.&quot;:&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
sed &#39;s#^\([a-zA-Z]\).* \([a-zA-Z]\).*#\2., \1.#g&#39;&lt;/div&gt;
&lt;br /&gt;
... if you were sitting over here, you&#39;d be watching my eyes bleed right now. Also, I&#39;m pretty sure that the code is buggy and might even erase my hard drive.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
A New Hope.&lt;/h3&gt;
&lt;a href=&quot;http://people.csail.mit.edu/emina/&quot;&gt;Emina Torlak&lt;/a&gt; and I spent the last couple of days tweaking a synthesizer that can generate the above Sed scripts from just &lt;b&gt;two&lt;/b&gt; examples:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; (syn-sed&lt;br /&gt;
&amp;nbsp; &amp;nbsp;&#39;((&quot;Leo Meyerovich&quot; (&quot;L&quot; &quot;M&quot;) &quot;M., L.&quot;)&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;(&quot;Emina Torlak&quot; (&quot;E&quot; &quot;T&quot;) &quot;T., E.&quot;))&lt;br /&gt;
&amp;nbsp; &amp;nbsp;`(? &quot;., &quot; ? &quot;.&quot;))&lt;br /&gt;
&lt;br /&gt;
Each example specifies a name, what text to pull out of it, and the rewritten result. The last line defines a result template where the &quot;?&quot; symbols should get replaced by some of the input text.**&lt;br /&gt;
&lt;br /&gt;
The &quot;syn-sed&quot; function will generate code that works like the Sed script above but without harming any animals. The relationship is strong: in theory, if you let your computer spin long enough, it will recreate any sed formula. As the tool outputs the desired formula, it also serves as a gentler onboarding to learning and using regular expressions. Going back to my biologist friend, that&#39;s a big deal.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Automating Test-Driven Development.&lt;/h3&gt;
Regular expressions are tricky; we constantly have to test them on examples and tweak them until they work. The synthesis approach asks you to write down the input/output tests (specifications are good, right?), and in return, automates the crazy tweaking for you. If you ever find an example that doesn&#39;t work, instead of reverse engineering the regular expression and tweaking it, just add the new input/output test specification to the list of examples.&lt;br /&gt;
&lt;br /&gt;
The regular expressions are just the beginning of what &amp;nbsp;I&#39;ll show program synthesis can do, &lt;a href=&quot;https://thestrangeloop.com/sessions/thinking-dsls-for-massive-visualization&quot;&gt;so see you at the talk!&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Note: L* and other algorithms provide inference techniques specific to characterizing a regular language; the Sed example&#39;s use of a rewrite rule shows that we want synthesis for all the other DSLs too. For an amazing version of the regular expression scenario, check out&amp;nbsp;&lt;a href=&quot;http://www.youtube.com/watch?v=qHkgJFJR5cM&quot;&gt;Excel&#39;s new FlashFill!&lt;/a&gt;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;**: I bet we can eliminate the result template with some more hacking.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/7781378948983370348/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/7781378948983370348' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/7781378948983370348'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/7781378948983370348'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2013/09/sneak-peek-for-my-strange-loop-talk-on.html' title='Sneak Peek for My Strange Loop Talk on Parallel Program Synthesis'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-2324025976172641097</id><published>2013-08-03T13:31:00.004-07:00</published><updated>2013-08-03T13:31:52.943-07:00</updated><title type='text'>Startup Name Picker: Stage II</title><content type='html'>We&#39;re on to the second stage of picking our startup name. I&#39;d love to &lt;a href=&quot;https://docs.google.com/forms/d/1AM0sBcY_6tAoKPUrP3Y6rXGOJnMBjf41MuEKNEsqOwA/viewform&quot;&gt;learn what you think!&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
In a couple more weeks, I&#39;ll describe the data analysis we&#39;re using to break down the results. </content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/2324025976172641097/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/2324025976172641097' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/2324025976172641097'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/2324025976172641097'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2013/08/startup-name-picker-stage-ii.html' title='Startup Name Picker: Stage II'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-1248019637454014975</id><published>2013-07-31T12:19:00.001-07:00</published><updated>2013-07-31T12:19:13.262-07:00</updated><title type='text'>OOPSLA Preprint: Empirical Analysis of Programming Language Adoption</title><content type='html'>We put up a preprint of our analysis of &lt;a href=&quot;http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/papers/oopsla2013.pdf&quot;&gt;how languages spread and developers adopt them&lt;/a&gt;. The camera ready is coming, so any feedback would be welcome. If anyone is extra ambitious, I&#39;d love help in using our data to estimate the total number of languages out there :) The basic idea is to use a &lt;a href=&quot;http://www.jstatsoft.org/v40/i09/paper&quot;&gt;species estimator&lt;/a&gt; given our power law findings. &lt;br /&gt;
&lt;br /&gt;
At the same time, I&#39;m doing a lot of traveling in the next couple of months, and would love to meet up with folks:&lt;br /&gt;
&lt;ul class=&quot;txt&quot;&gt;
&lt;li&gt;Hawaii, mid August&lt;/li&gt;
&lt;li&gt;Denmark, late August (IFIP WGLD) &lt;/li&gt;
&lt;li&gt;Germany, early September&lt;/li&gt;
&lt;li&gt;Missouri, mid September (Emerging Languages / Strange Loop)&lt;/li&gt;
&lt;li&gt;NY/NJ, mid September&amp;nbsp; (IBM PL Day)&lt;/li&gt;
&lt;li&gt;Tentative: RI, mid September&lt;/li&gt;
&lt;/ul&gt;
</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/1248019637454014975/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/1248019637454014975' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/1248019637454014975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/1248019637454014975'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2013/07/oopsla-preprint-empirical-analysis-of.html' title='OOPSLA Preprint: Empirical Analysis of Programming Language Adoption'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-4670352670909485702</id><published>2013-07-20T18:23:00.001-07:00</published><updated>2013-07-20T20:18:27.443-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="big data visualization"/><category scheme="http://www.blogger.com/atom/ns#" term="startup"/><category scheme="http://www.blogger.com/atom/ns#" term="superconductor"/><title type='text'>Name Our Startup!</title><content type='html'>Exciting news: we&#39;re launching a data visualization startup!&lt;br /&gt;
&lt;br /&gt;
It is going to push the &lt;a href=&quot;http://superconductor.github.io/superconductor/demos/&quot;&gt;Superconductor project&lt;/a&gt;&amp;nbsp;forward: we&#39;re building a service for prebuilt big data visualizations that help data analysts explore their data and analytics providers to report their results. Launching the company will enable us to keep hacking on the open source core while pushing forward with new ideas. Keep an eye on this blog as I write about what happens as part of founding a tech startup in the Bay Area.&lt;br /&gt;
&lt;br /&gt;
In the meanwhile, if you&#39;ve ever thought about naming a company, &lt;a href=&quot;https://docs.google.com/forms/d/1dtRtFOmWZKusACkRrGL29UAN0BhK6pBDD3_Yhqq-cms/viewform&quot;&gt;I&#39;ve love for you to help pick ours by filling out a quick survey&lt;/a&gt;. Inspired by our colleagues at Mozilla, I&#39;m going to be transparent where possible. An option in the survey lets you sign up to get involved with fun decisions like this one in the future.&lt;br /&gt;
&lt;br /&gt;
Happy hacking!</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/4670352670909485702/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/4670352670909485702' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/4670352670909485702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/4670352670909485702'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2013/07/name-our-startup.html' title='Name Our Startup!'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-7307649704203436196</id><published>2013-06-26T19:45:00.005-07:00</published><updated>2013-07-20T20:18:08.480-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="power law"/><category scheme="http://www.blogger.com/atom/ns#" term="programming language adoption"/><category scheme="http://www.blogger.com/atom/ns#" term="socio-plt"/><title type='text'>Programming Language Popularity Revisited: Power Law vs. Exponential</title><content type='html'>Understanding the &#39;tail&#39; behavior of programming language popularity can help tell practicing language designers whether to sink effort into a domain specific language for a niche audience (long tail) vs. focusing on winner-takes-all with general purpose languages (short tail). I previously showed an &lt;a href=&quot;http://lmeyerov.blogspot.com/2012/07/socio-plt-camera-ready-and-glimpse-at.html&quot;&gt;analysis of languages in 200,000+ SourceForge projects from 2000-2010&lt;/a&gt;, which found popularity to follow an exponential curve. That means a short tail and most language use on SourceForge is centered in the big languages... or does it?&lt;br /&gt;
&lt;br /&gt;
I cross-validated the result today with two other data sources: Ohloh stats of 500,000+ projects across different open source repositories, and our survey of 1,600+ Wired, Slashdot, etc. readers that asked about the primary language for their most recent project. Ohloh also shows exponential short tail behavior, but not our Survey. What the heck happened, right?&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijS3orcahsnHEIFEydPJAphYt3LHZjUjRtvwhg3duxcFdw0FQKu3VJAIf4HVrytVL_S6hj_SipRk_BQSqR8gwhpRpb4G2qQDPJIFOufpc9nayBXwCfb5locfjkJf-b9FSib28uoIDfblc/s1600/popularity.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;240&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijS3orcahsnHEIFEydPJAphYt3LHZjUjRtvwhg3duxcFdw0FQKu3VJAIf4HVrytVL_S6hj_SipRk_BQSqR8gwhpRpb4G2qQDPJIFOufpc9nayBXwCfb5locfjkJf-b9FSib28uoIDfblc/s400/popularity.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;Conflicting cross-validation.&amp;nbsp;&lt;/b&gt;The red and green exponential curves drop off in popularity starting around the bottom half of the languages. In contrast, just like there being a page for everything on the web, the blue power law line keeps going.&lt;br /&gt;
&lt;br /&gt;
My first thought was that the data sets were measuring different things. Maybe commercial behavior is different from open source, but lines have blurred nowadays. It could have been that the SourceForge data was from 2-4 years before the others -- but both the survey and Ohloh were recent and in conflict. &amp;nbsp;Or, perhaps, it&#39;s the double-dipping in Ohloh from counting any project a language is used in, rather than measuring just for when its the primary language. These differences are real, &amp;nbsp;but I realized a simple but deadly methodological issue is at play.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;&lt;b&gt;&lt;span style=&quot;color: red;&quot;&gt;SourceForge and Ohloh curate their list of languages!&lt;/span&gt;&lt;/b&gt;&amp;nbsp;&lt;/i&gt;They only have about 100 languages -- if a language is not in their list, its use in a project will not be counted. The languages that would make up the long tail are not being counted! To get a taste, our survey was of magnitudes less people, yet it elicited 20% more languages. The survey measures what actual developers do, while my SourceForge and Ohloh data crunching was a &lt;i&gt;meta-analysis&lt;/i&gt;&amp;nbsp;restricted to&amp;nbsp;what SourceForge/Ohloh chose to annotate. Other techniques, such as trawling Google search results as in &lt;a href=&quot;http://langpop.com/&quot;&gt;langpop.com&lt;/a&gt;, are therefore similarly suspect for this style of curve fitting.&lt;br /&gt;
&lt;br /&gt;
Going forward, I&#39;d like to predict, for example, what an estimated tail of SourceForge and Ohloh language popularity would look if we assume its similar to the survey data. Furthermore, I&#39;d like to test whether SourceForge and Ohloh are actually power laws once the truncated data set is considered (e.g., is the completion using survey data a power law?). My stats skills bottom out at what&#39;s posted here, unfortunately -- if this sounds like your type of thing, I&#39;d love to talk :)&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJm9TyYfbmpEra0iJxx25LsNGWjn1nQXrU3qSfGqnZYEd2eVYqb28HIloE7DIjRurU8-gFNw4CGWvEqwNQ0VoUxUg8CTkCxpHbUqRn7spQtyWmM5ndyb2rI69fvwxHjXrgfUO403XQ25E/s1600/pop2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;312&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJm9TyYfbmpEra0iJxx25LsNGWjn1nQXrU3qSfGqnZYEd2eVYqb28HIloE7DIjRurU8-gFNw4CGWvEqwNQ0VoUxUg8CTkCxpHbUqRn7spQtyWmM5ndyb2rI69fvwxHjXrgfUO403XQ25E/s400/pop2.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;i&gt;Just for fun: the cumulative distributions with matching trendlines&lt;/i&gt;&lt;/div&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/7307649704203436196/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/7307649704203436196' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/7307649704203436196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/7307649704203436196'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2013/06/programming-language-popularity.html' title='Programming Language Popularity Revisited: Power Law vs. Exponential'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijS3orcahsnHEIFEydPJAphYt3LHZjUjRtvwhg3duxcFdw0FQKu3VJAIf4HVrytVL_S6hj_SipRk_BQSqR8gwhpRpb4G2qQDPJIFOufpc9nayBXwCfb5locfjkJf-b9FSib28uoIDfblc/s72-c/popularity.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-206539252143436024</id><published>2013-06-24T19:45:00.003-07:00</published><updated>2013-07-20T20:17:41.375-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="big data visualization"/><category scheme="http://www.blogger.com/atom/ns#" term="parallel browser"/><category scheme="http://www.blogger.com/atom/ns#" term="superconductor"/><title type='text'>Superconductor-as-a-service</title><content type='html'>We just got Superconductor running as a web service on EC2. You no longer need to install the compiler to get started! There&#39;s still a ways to go to make this fully usable, but the hardest part is done.&lt;br /&gt;
&lt;br /&gt;
Currently, the compiler service outputs unoptimized JavaScript. Send a POST request of a JSON object to our service and you&#39;ll get the synthesized layout engine:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(221, 221, 221); color: #333333; font-family: Consolas, &#39;Liberation Mono&#39;, Courier, monospace; font-size: 13px; line-height: 19px; margin-bottom: 15px; margin-top: 15px; overflow: auto; padding: 6px 10px;&quot;&gt; &lt;span class=&quot;kd&quot; style=&quot;font-weight: bold;&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;font-weight: bold;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot; style=&quot;color: #dd1144;&quot;&gt;&quot;interface I {} class C : I { children {} attributes { var x : int; } actions { x := 1; }}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;kd&quot; style=&quot;font-weight: bold;&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myRequest&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;font-weight: bold;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot; style=&quot;font-weight: bold;&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;font-weight: bold;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #dd1144;&quot;&gt;&#39;http://ec2-54-218-69-113.us-west-2.compute.amazonaws.com/compile/&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;font-weight: bold;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #dd1144;&quot;&gt;&#39;POST&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;font-weight: bold;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
            &lt;span class=&quot;s1&quot; style=&quot;color: #dd1144;&quot;&gt;&#39;ftl&#39;&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;font-weight: bold;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s1&quot; style=&quot;color: #dd1144;&quot;&gt;&#39;target&#39;&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;font-weight: bold;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #dd1144;&quot;&gt;&#39;js&#39;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}),&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;onSuccess&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;font-weight: bold;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot; style=&quot;font-weight: bold;&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot; style=&quot;color: #dd1144;&quot;&gt;&quot;received from server: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;font-weight: bold;&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;font-weight: bold;&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s2&quot; style=&quot;color: #dd1144;&quot;&gt;&quot; characters&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot; style=&quot;font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;color: #009999;&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;color: #009999;&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;font-weight: bold;&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot; style=&quot;color: #dd1144;&quot;&gt;&quot;error:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot; style=&quot;color: #dd1144;&quot;&gt;&quot;Synthesis error: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;font-weight: bold;&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;color: #009999;&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
            &lt;span class=&quot;k&quot; style=&quot;font-weight: bold;&quot;&gt;else&lt;/span&gt;
                &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #dd1144;&quot;&gt;&#39;result&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/pre&gt;
Switching to this compiler service model is exciting in a few ways, but the first two important ones will be:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;b&gt;Legacy&lt;/b&gt;: as the FTL language upgrades, we&#39;ll just keep legacy compilers running. You won&#39;t need to see the bitrot for running legacy files. Once the API and site mature, we&#39;ll lock it in.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Multiple backends: &lt;/b&gt;as hinted by the &#39;target&#39; field, we&#39;re going to start exposing our multiple backends. Right now the naive JavaScript one is up, and next on bat is WebCL.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
To play around, I posted an &lt;a href=&quot;http://jsfiddle.net/lmeyerov/Awubf/&quot;&gt;interactive fiddle&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/206539252143436024/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/206539252143436024' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/206539252143436024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/206539252143436024'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2013/06/superconductor-as-service.html' title='Superconductor-as-a-service'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-3075845002612579985</id><published>2013-05-22T13:59:00.001-07:00</published><updated>2013-05-22T15:11:35.233-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="multicore"/><category scheme="http://www.blogger.com/atom/ns#" term="parallel browser"/><category scheme="http://www.blogger.com/atom/ns#" term="superconductor"/><category scheme="http://www.blogger.com/atom/ns#" term="work stealing"/><title type='text'>How We Fixed Temporal Locality of Work Stealing for the Parallel Browser </title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlF4GeujDkSyW141PNijBRFy6Ny8N7g8EzPjGaoBtMFaRJVEctZY4vOwEv0DX3eZibiAdmNs0RJrU1LDzmFmUPLzH20DtRpFGnYfx2Xo1L7kR8RVSQn6rTSH-pWnbaNWBDAa8b2d_0Cco/s1600/workstealmulti.tiff&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;235&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlF4GeujDkSyW141PNijBRFy6Ny8N7g8EzPjGaoBtMFaRJVEctZY4vOwEv0DX3eZibiAdmNs0RJrU1LDzmFmUPLzH20DtRpFGnYfx2Xo1L7kR8RVSQn6rTSH-pWnbaNWBDAa8b2d_0Cco/s320/workstealmulti.tiff&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;b&gt;Broken Temporal Locality in Work Stealing&lt;/b&gt;:&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
Red shading indicates a temporally-induced miss.&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
The end of my&amp;nbsp;&lt;a href=&quot;http://lmeyerov.blogspot.com/2013/05/visualize-parallel-work-stealing-in.html&quot;&gt;last post&lt;/a&gt;&amp;nbsp;mentioned a big problem with work stealing: it has no temporal locality. For example, if a layout engine traverses Wikipedia&#39;s HTML nodes twice, 2/3rds of the nodes would move to different threads for the second traversal. To understand such a harsh critique and how we tackled it, you can try running the next version of the visualization:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;background-color: white; color: blue; font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;var s = document.createElement(&quot;script&quot;);&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; color: blue; font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;s.type = &#39;text/javascript&#39;;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; color: blue; font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;s.src = &#39;https://raw.github.com/lmeyerov/devnull/master/one-offs/workstealMulti.js&#39;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; color: blue; font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;document.getElementsByTagName(&#39;head&#39;)[0].appendChild(s);&lt;/span&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;b&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;Run visualization by putting into your browser&#39;s JavaScript console&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;br /&gt;
Open a website, go to the JavaScript console, and put in that script. Hit the run button on the top-left once to do a normal work stealing traversal, and once the traversal finishes, hit the button again to run another pass. The first pass uses colors to show which thread got which node. As described in the previous post, spatial and intra-traversal temporal locality are great. The second pass switches to blue/red coloring to show, on the second pass, if a thread got the same node (blue) or a different one (red).&lt;br /&gt;
&lt;br /&gt;
What we see is that, near the beginning of the second pass, work stealing is great: lots of blue near the top of the page. As the traversal continues, however, slight deviations occur. These compound, so the longer the schedule, the more random the assignment. &amp;nbsp;By the end of the traversal, only 33% of the nodes were temporal hits. Not good! Our parallel layout engines do 3-9 passes, and often the data used in one pass is computed in the previous one, so that hurts.&lt;br /&gt;
&lt;br /&gt;
For the parallel browser, we had a simple and effective solution: just record the old schedule and reuse it. This worked because it does several passes in succession of a big tree. Temporal locality isn&#39;t an issue for the first traversal, so we use work stealing to find a load balanced schedule. For subsequent traversals, we play the schedule forwards (top-down traversal) or backwards (bottom-up). We lose a bit of load balancing, but not much in practice (hurray big trees!), and gain a bit by lowering overheads (no dynamic queues etc., just p2p locking). Simple to implement and we&#39;ve seen near-ideal scaling: 80-95% of ideal on 4-8 cores.&lt;br /&gt;
&lt;br /&gt;
We did this work years ago, and since then, others have published nice generalizations. &amp;nbsp;Common elements of &lt;a href=&quot;http://scholar.google.com/scholar?hl=en&amp;amp;q=locality+aware+work+stealing&amp;amp;btnG=&amp;amp;as_sdt=1%2C5&amp;amp;as_sdtp=&quot;&gt;locality-aware work stealing schedulers&lt;/a&gt; are allowing programmers to annotate locality groups (e.g., mark a node as part of a subtree/tile) or using static/dynamic analysis to infer it, &amp;nbsp;and then using that information to pick the steal. I&#39;m not aware of any that are smart enough to &#39;wait&#39; as in our case, but it&#39;s a sensible next step in profile-guided systems. See &lt;a href=&quot;http://research.microsoft.com/en-us/um/people/trishulc/pubs.htm&quot;&gt;Trishul Chilimbi&#39;s late 90&#39;s thesis work&lt;/a&gt; to get in the right mindset.</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/3075845002612579985/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/3075845002612579985' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/3075845002612579985'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/3075845002612579985'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2013/05/how-we-fixed-temporal-locality-of-work.html' title='How We Fixed Temporal Locality of Work Stealing for the Parallel Browser '/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlF4GeujDkSyW141PNijBRFy6Ny8N7g8EzPjGaoBtMFaRJVEctZY4vOwEv0DX3eZibiAdmNs0RJrU1LDzmFmUPLzH20DtRpFGnYfx2Xo1L7kR8RVSQn6rTSH-pWnbaNWBDAa8b2d_0Cco/s72-c/workstealmulti.tiff" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-2445867660218946105</id><published>2013-05-05T16:24:00.003-07:00</published><updated>2013-05-22T15:06:10.912-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="multicore"/><category scheme="http://www.blogger.com/atom/ns#" term="parallel browser"/><category scheme="http://www.blogger.com/atom/ns#" term="superconductor"/><category scheme="http://www.blogger.com/atom/ns#" term="work stealing"/><title type='text'>Visualize Parallel Work Stealing in the Browser</title><content type='html'>I try to write at least one interesting program every week. This weekend, to spice up my dissertation talk, I built an animated visualization of how my parallel CSS engine partitions a webpage via &lt;a href=&quot;http://en.wikipedia.org/wiki/Cilk&quot;&gt;work stealing&lt;/a&gt;.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYeC37enIAfsg3Zen92NVpF3VzyBciTF_sOTA0gssXZkCaDEd56cHAOpPbOpgjdNM6TcefXSFtBNU7M0bAxvSipzAbjNKyNGDOxZgyB3w6anhJ02eVpJoXfEse39v9BRrA2Uic_cuk-mc/s1600/workstealss.tiff&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;239&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYeC37enIAfsg3Zen92NVpF3VzyBciTF_sOTA0gssXZkCaDEd56cHAOpPbOpgjdNM6TcefXSFtBNU7M0bAxvSipzAbjNKyNGDOxZgyB3w6anhJ02eVpJoXfEse39v9BRrA2Uic_cuk-mc/s320/workstealss.tiff&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Work stealing is a great parallel task scheduling algorithm that provides dynamic load balancing and spatial locality. The idea is that each thread has a local queue of ready-to-fire tasks that it loops through, and if it ever runs out of local tasks, it will &lt;i&gt;steal&lt;/i&gt;&amp;nbsp;tasks from another thread&#39;s queue. The visualization shows how this works for a parallel top-down tree traversal over a webpage&#39;s HTML tree. In this case, a task is a node, and executing a task is denoted by changing the background color of that node to match the thread&#39;s color. The node&#39;s children are then added to the local queue for firing, and the process repeats. Whenever one thread steals a task from another, the webpage node corresponding to the stolen task has its border highlighted by the color of the thieving thread.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
To try it it out, open your favorite website, paste the following code into the JavaScript console, and hit the start button:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;span style=&quot;color: blue; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;var s = document.createElement(&quot;script&quot;);&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: blue; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;s.type = &#39;text/javascript&#39;;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: blue; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;s.src = &#39;https://raw.github.com/lmeyerov/devnull/master/one-offs/worksteal.js&#39;;&amp;nbsp;
  &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: blue; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;document.getElementsByTagName(&#39;head&#39;)[0].appendChild(s);
&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
Alternatively, copy the following into your URL bar and hit start after it loads:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;color: blue; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;javascript:(function(){var s = document.createElement(&quot;script&quot;); s.type = &#39;text/javascript&#39;; s.src = &#39;https://raw.github.com/lmeyerov/devnull/master/one-offs/worksteal.js&#39;; document.getElementsByTagName(&#39;head&#39;)[0].appendChild(s); }())&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
For this version, make sure you browser doesn&#39;t strip the &quot;&lt;span style=&quot;color: blue; font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;javascript:&lt;/span&gt;&quot; at the front.&lt;br /&gt;
&lt;br /&gt;
The animation shows several important things for parallelization. First, the same thread will run many tasks that are near each other, which indicates good spatial locality. The evidence of this occurring is that many regions of the webpage will share the same color. Second, steals are infrequent, which keeps overheads low and again highlights locality benefits. This shows up in the page as very few stolen nodes (colored borders). To measure it, the per-thread percentage counters at top show the ratio of stolen nodes to non-stolen ones, and on most webpages, I get a pleasingly low 5% miss rate. &amp;nbsp;Finally, you can see a problem with the algorithm: the steal rate spikes at the beginning and end of a tree traversal. I made a simple optimization to the initial traversal -- I do a short sequential BFS traversal rather than immediately start with parallel DFS -- but did nothing here for the end.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
My layout engine actually uses a novel semi-static work stealer rather Cilk-style dynamic work stealing. The reason is that Cilk does not account for temporal locality, which is important in situations such as multiple traversals over a tree because they revisit the same nodes over time. With Cilk-style scheduling, which thread a node lands on can easily change across different traversals, which is a huge hit. Instead, my approach is to use work stealing once to partition the tree, and then reuse the precomputed schedule across different traversals: load balancing suffers a bit, but temporal locality goes up.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Enjoy!&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/2445867660218946105/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/2445867660218946105' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/2445867660218946105'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/2445867660218946105'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2013/05/visualize-parallel-work-stealing-in.html' title='Visualize Parallel Work Stealing in the Browser'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYeC37enIAfsg3Zen92NVpF3VzyBciTF_sOTA0gssXZkCaDEd56cHAOpPbOpgjdNM6TcefXSFtBNU7M0bAxvSipzAbjNKyNGDOxZgyB3w6anhJ02eVpJoXfEse39v9BRrA2Uic_cuk-mc/s72-c/workstealss.tiff" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-1618955734800630770</id><published>2013-05-03T21:11:00.000-07:00</published><updated>2013-05-03T22:10:47.627-07:00</updated><title type='text'>Monday, Monday, Monday! Dissertation Talk</title><content type='html'>&lt;br /&gt;
About time.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;
&lt;i&gt;Your message for list eecs-announce has been forwarded to editor(s):&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;p1&quot;&gt;
&lt;b&gt;[Dissertation Talk] Parallelizing the Browser: Synthesis and Optimization of Parallel Tree Traversals&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;p1&quot;&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br class=&quot;Apple-interchange-newline&quot; /&gt;Speaker: Leo Meyerovich&lt;br /&gt;
Advisor: &amp;nbsp;Rastislav Bodik&lt;br /&gt;
Date: Monday, May 13th, 2013&lt;br /&gt;
Time: 3:30pm&lt;br /&gt;
Room: 373 Soda Hall&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
ABSTRACT:&lt;br /&gt;
From low-power phones to speed-hungry data visualizations, web browsers need a performance boost. Parallelization is an attractive opportunity because commodity client devices already feature multicore, subword-SIMD, and GPU hardware. However, a typical webpage will not strongly benefit from modern hardware because browsers were only designed for sequential execution. We therefore need to redesign browsers to be parallel. This thesis focuses on a browser component that we found to be particularly challenging: the layout engine.&lt;br /&gt;
&lt;br /&gt;
We address layout engine implementation by identifying its surprising connection with attribute grammars and then solving key ensuing challenges:&lt;br /&gt;
&lt;br /&gt;
1. We show how layout engines, both for documents and data visualization, can often be functionally specified in our extended form of attribute grammars.&lt;br /&gt;
&lt;br /&gt;
2. We introduce a synthesizer that automatically schedules an attribute grammar as a composition of parallel tree traversals. Notably, our synthesizer is fast, simple to extend, and finds schedules that assist aggressive code generation.&lt;br /&gt;
&lt;br /&gt;
3. We make editing parallel code safe by introducing a simple programming construct for partial behavioral specification: schedule sketching.&lt;br /&gt;
&lt;br /&gt;
4. We optimize tree traversals for SIMD, MIMD, and GPU architectures at tree load time through novel data representation and scheduling optimizations.&lt;br /&gt;
&lt;br /&gt;
Put together, we generated a parallel CSS document layout engine that can mostly render complex sites such as Wikipedia. Furthermore, we ran data visualizations in the browser that support interacting with over 100,000 data points in real time.</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/1618955734800630770/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/1618955734800630770' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/1618955734800630770'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/1618955734800630770'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2013/05/monday-monday-monday-dissertation-talk.html' title='Monday, Monday, Monday! Dissertation Talk'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-65073785676686260</id><published>2013-04-07T15:54:00.000-07:00</published><updated>2013-05-22T15:05:50.615-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="json"/><category scheme="http://www.blogger.com/atom/ns#" term="multicore"/><category scheme="http://www.blogger.com/atom/ns#" term="parallel browser"/><category scheme="http://www.blogger.com/atom/ns#" term="superconductor"/><category scheme="http://www.blogger.com/atom/ns#" term="web worker"/><title type='text'>Parallel Parsing isn&#39;t Hard (Or, Parallel JSON via Web Workers!)</title><content type='html'>&lt;b&gt;Generalized parallel parsing is hard.&amp;nbsp;&lt;/b&gt;Many a Ph.D. has been burned by attempting parallel parsing. Guy Steele wrote papers about it, and you&#39;ll find custom ones for favorite modern technology X for X = JavaScript, HTML, XML, etc. However, in practice, practical parallel parsing does not have to be so hard because parallel parsing research generally focuses on extreme cases. For example, our group examined &lt;i&gt;automatically generating&lt;/i&gt;&amp;nbsp;parallel parsers and handling &lt;i&gt;arbitrary&lt;/i&gt;&amp;nbsp;HTML.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Actual parallel parsing is easy.&lt;/b&gt;&amp;nbsp;Real applications provide significantly simplifying assumptions. Case in point: for our browser-based big data visualization framework, we needed to somehow load in big JSON arrays. Modern browsers provide a fast native function &quot;JSON.parse :: String -&amp;gt; JSObj&quot; that is fine for normal sized data sets, but parsing 9MB of sparse data takes over 1s, which requires a loading screen and eats your battery. The solution took ~2 days: on the server, split the data into multiple arrays, and on the client, use web workers to parse each array in parallel. Even though I&#39;m controlling the parsing in JavaScript, the actual parsing is still being done natively by calling into JSON.parse for handling each fragment.&lt;br /&gt;
&lt;br /&gt;
Anyways, the proof is in the pudding. The relevant benchmarks are impact on file size and load time.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Benchmark 1: file size&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJS56H8JzVydZfUtoYvFywBghotnNfCkojw6i8c73lmwnmuRKP1fJmVc677qaAbTv00y6Jon_BqgKx8pmPq1EZUQgSkqS9GVr4bJl0VxYQTo-tVUQfV6x1yDC7U7xRTQzYVxQR03OmJPM/s1600/filesize.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;203&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJS56H8JzVydZfUtoYvFywBghotnNfCkojw6i8c73lmwnmuRKP1fJmVc677qaAbTv00y6Jon_BqgKx8pmPq1EZUQgSkqS9GVr4bJl0VxYQTo-tVUQfV6x1yDC7U7xRTQzYVxQR03OmJPM/s320/filesize.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Splitting one of our sparse JSON data files into multiple chunks has no real hit to the file size, and due to some uninteresting &amp;nbsp;phenomena, actually helps when gzip is used. I&#39;m also showing the benefit of compressing repeating zeros (&quot;sparse json&quot;) for our particular data set.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Benchmark 2: speedup&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBg4jv8ImplyghSlsr6MnxpYjz68vJQB84dAxg2gk-gzprfIusFhcEEDpvp0U3zbeoZbCirlRiDoBrt58nwGuSNJ54Mqcbn0e7Blu4SvnXsqTZyd2Aa_rePUpuZxjsIuX71ulurIiL-aw/s1600/speedup.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;197&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBg4jv8ImplyghSlsr6MnxpYjz68vJQB84dAxg2gk-gzprfIusFhcEEDpvp0U3zbeoZbCirlRiDoBrt58nwGuSNJ54Mqcbn0e7Blu4SvnXsqTZyd2Aa_rePUpuZxjsIuX71ulurIiL-aw/s320/speedup.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
For the second benchmark, I&#39;m testing loading the data set from a local hard drive when using different formats. The first two columns are sequential data formats, and with the second column primarily demonstrating the benefit of doing preprocessing for my particular application. The blue part of each column shows, in ms, how much time is spent reading the file from disk and parsing it.&lt;br /&gt;
&lt;br /&gt;
The important part is comparing the blue of the third column against the blue part of the second: using workers to parse JSON chunks is 2x faster than parsing the file in one sequential go.&lt;br /&gt;
&lt;br /&gt;
For further parallel speedups, it is important to realize that this application hit &lt;a href=&quot;http://en.wikipedia.org/wiki/Amdahl&#39;s_law&quot;&gt;Amdahl&#39;s Law&lt;/a&gt;. In particular, the sequential stuff, like the black subcolumns, must be parallelized. The blue columns also have sequential code due to APIs I&#39;m using. First, Safari does not have zero-copy message passing (&lt;i&gt;&lt;a href=&quot;http://updates.html5rocks.com/2011/12/Transferable-Objects-Lightning-Fast&quot;&gt;transferable objects&lt;/a&gt;&lt;/i&gt;), so a sequential copy is made in communicating a parsed fragment back to the master. Second, I&#39;m actually creating a big typed array, so even current web worker APIs do not help: I want to the Buffer &lt;i&gt;into&lt;/i&gt;&amp;nbsp;the worker, not get a new buffer out of one, which means I have to do a sequential copy even in Firefox and Chrome. Basically, we&#39;re seeing the web&#39;s poor support of message &amp;nbsp;passing forcing a lot of slow, sequential copies.&lt;br /&gt;
&lt;br /&gt;
Finally, I only benchmarked the case of local file loads. Our application, ultimately, will be used online with a server providing the data on-the-fly. The optimizations I showed should still help even if the application is network bound: they &lt;i&gt;also&lt;/i&gt;&amp;nbsp;enable pipeline parallelism. By splitting the JSON, parsing one chunk is now done in parallel with&amp;nbsp;downloading&amp;nbsp;the next. Modern webpages alternate between waiting on the network and the CPU, which this solution&amp;nbsp;elegantly&amp;nbsp;addresses.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
So there you have it -- parallel parsing, &lt;i&gt;in practice&lt;/i&gt;, should be easy. I did a constrained case of handling big JSON arrays. Even for more general JSON, it should only take a day more of work: partition the JSON via work stealing -- I successfully did a similar thing in my thesis for HTML in a few hundred lines of C++.&lt;br /&gt;
&lt;br /&gt;
If you&#39;d like the code, it&#39;ll be part of our &lt;a href=&quot;http://sc-lang.com/&quot;&gt;Superconductor&lt;/a&gt; (automatically GPU-accelerated web programming framework for big data visualization) release next month. Ping me if you&#39;d be interested in working on parallel parsing of arbitrary JSON -- it should be awesome!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;UPDATE&lt;/b&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
I more carefully measured the overheads &amp;nbsp;and also did a couple more optimizations. The chart below shows the new results. It also now includes the message passing overheads in gray, where ~90% of it would go away in Chrome with &lt;i&gt;transferable objects&lt;/i&gt;&amp;nbsp;and the other 10% might be eliminated with ownership transfer of buffer views (sub-buffers), not just buffers.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCWNav9OF48j8UQ2j8hg9N2PtZSbHoHZ34NX6MUMpt66Woxcy9lIfudu4TMyla352egcAlyGvTVBb40QSMYyZAL-bQtpZCgfF2Ura5gng0O0eSL1P5JNWGRZ_omSs1E9A8oHF0vr-8ZII/s1600/speedup4.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;297&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCWNav9OF48j8UQ2j8hg9N2PtZSbHoHZ34NX6MUMpt66Woxcy9lIfudu4TMyla352egcAlyGvTVBb40QSMYyZAL-bQtpZCgfF2Ura5gng0O0eSL1P5JNWGRZ_omSs1E9A8oHF0vr-8ZII/s320/speedup4.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Two big &amp;nbsp;things are going on:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;The workers now perform decompression rather than the master. However, decompressing in the worker has a cost: &amp;nbsp;each worker now returns an inflated result message. Safari does not have ownership transfer so almost 100ms is spent copying the message back to the main thread rather than passing a pointer. &lt;br /&gt;&lt;br /&gt;The overhead is still worth it -- the blue region shrunk a lot, even if there is now a big gray region. (The gray region is in both because the sequential job runs in a worker in order to avoid pressuring the UI thread.) If/when Safari gets transferrable objects, 90% of the gray bars will disappear.&lt;/li&gt;
&lt;li&gt;Faster reduction of worker results into the final GPU buffer. Typed arrays support method&lt;b&gt;&amp;nbsp;set &lt;/b&gt;that can also help such reductions. It acts like a memcpy,&amp;nbsp;so &lt;b&gt;result.set(chunk, len)&lt;/b&gt;&amp;nbsp;copies array buffer &quot;chunk&quot; into array buffer &quot;result&quot; starting at byte offset &quot;len&quot; into &quot;result.&quot; It only takes about 13ms. If the typed array spec was extended so that disjoint sub-buffers could be transferred across workers, the other 10% of the gray bars would disappear.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/65073785676686260/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/65073785676686260' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/65073785676686260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/65073785676686260'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2013/04/parallel-parsing-isnt-hard-or-parallel.html' title='Parallel Parsing isn&#39;t Hard (Or, Parallel JSON via Web Workers!)'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJS56H8JzVydZfUtoYvFywBghotnNfCkojw6i8c73lmwnmuRKP1fJmVc677qaAbTv00y6Jon_BqgKx8pmPq1EZUQgSkqS9GVr4bJl0VxYQTo-tVUQfV6x1yDC7U7xRTQzYVxQR03OmJPM/s72-c/filesize.png" height="72" width="72"/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-7788115074971859600</id><published>2013-01-26T20:34:00.004-08:00</published><updated>2013-01-26T23:35:09.283-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="socio-plt"/><title type='text'>Adoption-Oriented Languages</title><content type='html'>&lt;b&gt;Language design decisions should not just increase adoption &lt;i&gt;but also&amp;nbsp;exploit adoption&lt;/i&gt;&lt;/b&gt;. For example, I just measured how popular languages can rely upon Stackoverflow as a code assistant. The chart below shows that increased language popularity on SourceForge (x axis) leads to faster answer times for questions asked on Stackoverflow (colored bins on the y axis):&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQovg_lsIbi4L7RNos8NEIKAWyI-JVIO5GYt4iDgRPtxjiJFgpvTAFcP_DWR45q1-IkP-hIWVlqWHQl8EqeixG9Js4aBdlcYCeLoyNE8ZKtwbRdo8A05c-sWbEoOFNhoo8ltkEt1xGveE/s1600/answertime.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;240&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQovg_lsIbi4L7RNos8NEIKAWyI-JVIO5GYt4iDgRPtxjiJFgpvTAFcP_DWR45q1-IkP-hIWVlqWHQl8EqeixG9Js4aBdlcYCeLoyNE8ZKtwbRdo8A05c-sWbEoOFNhoo8ltkEt1xGveE/s320/answertime.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;b&gt;Stackoverflow Time-to-Answer vs. Sourceforge.net Language Popularity.&amp;nbsp;&lt;/b&gt;&lt;i&gt;Raw data grabbed a&amp;nbsp;&lt;a href=&quot;http://data.stackexchange.com/stackoverflow/query/93755/time-to-answer-by-language-difficulty-since-2010&quot;&gt;stackoverflow query&lt;/a&gt;&amp;nbsp;that modifies&amp;nbsp;&lt;a href=&quot;http://blog.guillermowinkler.com/blog/2012/10/30/how-long-waiting-for-an-answer-in-stackoverflow/&quot;&gt;G. Winker&#39;s&lt;/a&gt;, and language rankings from&amp;nbsp;&lt;a href=&quot;http://lmeyerov.blogspot.com/2012/08/quantifying-social-influences-on.html&quot;&gt;our previous analysis&lt;/a&gt;.&lt;/i&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
Top 10 languages have questions answered within 5 hours over 80% of the time, but for languages worse than Top 50, that shrinks to only 50% of the time. In terms of a simple blocker at work, that&#39;s a big deal: you can reliably ask a question, go work on something else, and come back to the answer!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Of course, measuring response time vs. popularity is up to interpretation: it could be that as adoption increaess, people ask easier questions. However, I suspect the chart is actually undercounting the adoption benefit: the more questions are answered, the more people don&#39;t need to wait for answers because they can just search for old ones! As one measure, we see that a language&#39;s popularity relates to its answer corpus size:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLEfMYl3f3Paf8AYzJx6h4qUcSoZK-G_e5xHRtz579qgfX4dvkAgXIPtWQVdw00Pn8BrohDP3tDq5Ui-t0BfqdSB0hvLXRd-1sLqsFpTMPLipoV17WYB8zYqa3s-g3WC5Pgmv3Ho1Immg/s1600/answertime2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;240&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLEfMYl3f3Paf8AYzJx6h4qUcSoZK-G_e5xHRtz579qgfX4dvkAgXIPtWQVdw00Pn8BrohDP3tDq5Ui-t0BfqdSB0hvLXRd-1sLqsFpTMPLipoV17WYB8zYqa3s-g3WC5Pgmv3Ho1Immg/s320/answertime2.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;b&gt;&amp;nbsp;Stackoverflow Answer Corpus Size vs. Sourceforge.net Language Popularity.&lt;/b&gt; &lt;i&gt;Same dataset as above.&amp;nbsp;
&lt;/i&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
I had to switch to a log-scale axis for answers! For popular languages, search becomes a valuable tool because Stackoverflow alone provides a FAQ of 100,000 solutions. An enterprising individual might want to further examine the duplicate rate, which I suspect would provide an insightful indicator for the likelihood of a query already being answered by a previous response.


&lt;br /&gt;
&lt;br /&gt;
Open source library repos are another case of a feature that improves with adoption: the library of builtins is ever expanding. Likewise, one of my favorite research projects is &lt;a href=&quot;http://research.cs.wisc.edu/cbi/&quot;&gt;cooperative bug isolation&lt;/a&gt;, which exploits the adoption of a program to help narrow down causes of bugs. (AFAICT, most software companies do some form of tracking error and performance dumps.) A/B testing for feature design is also increasingly common. As another example, in academia, code completion tools are also &amp;nbsp;increasingly incorporating corpus-based solutions. A corpus can provide more value than type and namespace based solutions because, for example, synthesized code completions will resemble what people would actually write.&lt;br /&gt;
&lt;br /&gt;
I started sketching out the notion of &lt;b&gt;adoption-oriented language design&lt;/b&gt;&lt;i style=&quot;font-weight: bold;&quot;&gt;&amp;nbsp;&lt;/i&gt;in a &lt;a href=&quot;http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/papers/isat2013.pdf&quot;&gt;position paper last week&lt;/a&gt;. I struggled to think of features that &lt;i&gt;couldn&#39;t &lt;/i&gt;be designed to&amp;nbsp;strengthen with adoption. For example, verification, testing, security, program synthesis, and optimization could all be designed to &lt;i&gt;automatically&lt;/i&gt; exploit adoption of either the language, the library, or a program. &amp;nbsp;What strikes me is how little adoption is exploited today. &lt;b&gt;Outside of the cases, am I missing any that are commonly practiced, or should be?&lt;/b&gt;</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/7788115074971859600/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/7788115074971859600' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/7788115074971859600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/7788115074971859600'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2013/01/adoption-oriented-languages.html' title='Adoption-Oriented Languages'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQovg_lsIbi4L7RNos8NEIKAWyI-JVIO5GYt4iDgRPtxjiJFgpvTAFcP_DWR45q1-IkP-hIWVlqWHQl8EqeixG9Js4aBdlcYCeLoyNE8ZKtwbRdo8A05c-sWbEoOFNhoo8ltkEt1xGveE/s72-c/answertime.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-1611823033002294769</id><published>2013-01-20T19:43:00.000-08:00</published><updated>2013-01-26T23:06:57.658-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="parallel browser"/><title type='text'>Superconductor Language in Action: Easy Big Data Viz in Your Browser</title><content type='html'>Exciting news: we&#39;ll be talking about Superconductor at the &lt;a href=&quot;http://fluentconf.com/fluent2013&quot;&gt;O&#39;Reilly Fluent conference&lt;/a&gt;! This will be the first time we show it outside of small seminars, and will hopefully coincide with our open source release. This video proposing our session gives a feel for what Superconductor can do. The link skips right into the demo:&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;a href=&quot;http://www.youtube.com/watch?v=H1aHul6UaV4&amp;amp;feature=youtu.be&amp;amp;t=40s&quot;&gt;&lt;img src=&quot;http://img.youtube.com/vi/H1aHul6UaV4/0.jpg&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;br /&gt;
The basic idea is that you write a normalish webpage (HTML5, JS, JSON, CSS) for including and manipulating your big data viz, except:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Instead of relying up on the browser to run it (parse, layout, render, &amp;amp; animate), you load in our GPU-accelerated JavaScript libraries for the heavy lifting. Behind the scenes, we automatically exploit workers, WebCL, WebGL, etc.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Instead of using JavaScript for fancy layouts, you load in a widget made with our declarative layout DSL (or use it to define your own). Our parallel program synthesizer automatically finds the parallelism in the widget specs and our code generators output GPU code based on it.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
We&#39;re finally ramping up on a paper with the end-to-end system details; this will be the first time we discuss running inside of a commercial browser and using GPUs. Papers have a ridiculous delay period, so of you&#39;ll be at SIGGRAPH (LA), &lt;a href=&quot;http://ppopp2013.ics.uci.edu/&quot;&gt;PPOPP&lt;/a&gt;&amp;nbsp;(Shenzen, China), or Intel&#39;s TechFest (Portland), you&#39;ll be able to catch a demo before then.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/1611823033002294769/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/1611823033002294769' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/1611823033002294769'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/1611823033002294769'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2013/01/superconductor-language-in-action-easy.html' title='Superconductor Language in Action: Easy Big Data Viz in Your Browser'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-7660801575260877723</id><published>2012-12-26T19:10:00.006-08:00</published><updated>2013-01-26T23:07:13.022-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="flapjax"/><title type='text'>Reactive Objects and Arrays via Direct Proxies</title><content type='html'>Arrays are a crucial building block for programming. Consequently, an essential question for functional reactive programming is how to react to imperative array updates. Designing a clean interface gets bogged down in issues like identity, API consistency, and efficient incrementalization. I used a recent extension to JavaScript, &lt;a href=&quot;http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies&quot;&gt;Direct Proxies&lt;/a&gt;&amp;nbsp;(Firefox-only), &amp;nbsp;to &lt;a href=&quot;http://jsfiddle.net/lmeyerov/v9SRR/&quot;&gt;sketch a transparent dual-mode model&lt;/a&gt;&amp;nbsp;(JSFiddle)&amp;nbsp;for &lt;a href=&quot;http://flapjax-lang.org/&quot;&gt;Flapjax&lt;/a&gt;. I made a reactive&amp;nbsp;array interface that covers the entire Array interface and supports both &lt;i&gt;instant&lt;/i&gt; and &lt;i&gt;batched&lt;/i&gt; updates. A fun holiday break from &lt;a href=&quot;http://www.youtube.com/watch?v=H1aHul6UaV4&amp;amp;feature=youtu.be&amp;amp;t=40s&quot;&gt;Superconductor&lt;/a&gt; :)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;i&gt;Update: I generalized the code in two ways: it works with object instances and also allows choosing whether the prototype is &lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Array&lt;/span&gt; or &lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Behavior&lt;/span&gt;.&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
&lt;b&gt;Transparency&lt;/b&gt;&lt;/h3&gt;
&lt;br /&gt;
The idea is to create a reactive array that is tied to an existing normal array:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;var arr = [&#39;init&#39;],&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;var arrB = bindB(arr);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
From then on, interactions with one array are automatically reflected from one to the other. (In particular, &amp;nbsp;&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;arrB&lt;/span&gt; uses &lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;arr&lt;/span&gt; as its backing store and proxies interactions to it):&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;// assert(arr[0] == arrB[0]);&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;arr.push(&#39;a&#39;); &amp;nbsp;//&amp;nbsp;assert(arr.length == fxArr.length);&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;arrB.push(&#39;b&#39;); //&amp;nbsp;assert(arr.length == fxArr.length);&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
By defining traps for JavaScript&#39;s meta-object&amp;nbsp;&lt;a href=&quot;http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies&quot;&gt;proxy protocol&lt;/a&gt;, I guarantee that all of JavaScript&#39;s array methods are supported by the reactive array &lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;arrB&lt;/span&gt;. All in all, for normal JavaScript, it should not matter if you pass around&amp;nbsp;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;arr&lt;/span&gt;&amp;nbsp;or&amp;nbsp;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;arrB&lt;/span&gt;: they act on the same underlying data.&lt;br /&gt;
&lt;br /&gt;
(Full transparency might be wrong. I&#39;ll raise a semantic issue at the end about what if you *do* want to distinguish reactive arrays vs. flat ones using operators such as &lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;instanceof.&lt;/span&gt;In my implementation, I let you pick as an optional parameter to &lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;bindB&lt;/span&gt;.)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
Functional Reactivity and Instant Reactions&lt;/h3&gt;
&lt;div&gt;
&lt;br /&gt;
Now the cool thing is that array mutations can be &lt;i&gt;automatically&lt;/i&gt; reacted to using normal functional reactive programming constructs.&lt;br /&gt;
&lt;br /&gt;
For example, we can declare a live counter of the array size:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;insertDomB(arrB.liftB(function (av) { return av.length; }));&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The above snippet is the usual functional reactive code that is a joy to read. It displays the length of the array. Whenever &lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;arrB&lt;/span&gt; updates, the GUI will automatically update to show the correct length.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The new ability here is that wrapped array mutations automatically trigger reactions:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;arrB[30] = 20; //updates length counter on screen&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;arrB.push(&#39;hello&#39;);&amp;nbsp;//updates length counter on screen&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
I&#39;m calling these &lt;i style=&quot;font-weight: bold;&quot;&gt;instant&lt;/i&gt;&amp;nbsp;reactions because each mutation registers an update event. In the above statements, two update events will be fired, one for each statement.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The original array and reactive array refer to the same data, but differ on how they interact with the event system. Updates to the original array do not trigger reactions:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;arr.push(&#39;world&#39;); &amp;nbsp;//no screen update&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
Maintaining non-triggering behavior of the original array is important so that non-reactive code not ready for the extended behavior does not trigger massive DOM updates. In places where it is safe to do the switch,&amp;nbsp;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;arrB&lt;/span&gt;&amp;nbsp;can be swapped in.&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;h3&gt;
Batched Reactions&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;
A nice pattern falls out of the wrapped and unwrapped view of the array. When many updates to an array should happen, we can batch them for a single subsequent response:&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;function addSome(n, arrB) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp;&amp;nbsp;//batched update&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; for (var i = 0; i &amp;lt; n; i++) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;arrB.last.push(i);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; }&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; //notification&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; if (n &amp;lt; 0)&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;arrB[0] = arrB.last[0];&amp;nbsp;//updates length counter on screen&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;addSome(10, arrB);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The &quot;arrB.last.push(i)&quot; calls trigger no reactions, while the assignment to&amp;nbsp;arrB[0] triggers an instant&amp;nbsp;reaction. This pattern of silent array updates followed by an instant reaction on the reactive view is a &lt;i&gt;&lt;b&gt;batched reaction&lt;/b&gt;&lt;/i&gt;. It is largely an optimization, but if you create local invariants inside the body of addSome, you can also use the pattern for &amp;nbsp;(non-nested)&amp;nbsp;&lt;b&gt;&lt;i&gt;transactional&lt;/i&gt; &lt;i&gt;reactions&lt;/i&gt;&lt;/b&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Object Instances and Meta Protocols&lt;/h3&gt;
&lt;/div&gt;
In response to Shriram&#39;s comment, the technique here is a late-bound dual to &lt;a href=&quot;http://cs.brown.edu/~sk/Publications/Papers/Published/ick-adapt-oo-fwk-frp/&quot;&gt;his work in making legacy classes reactive&lt;/a&gt;. For Racket&#39;s class system, he showed how to make a reactive subclass: the case of arrays would act like &quot;&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;var myArrB = new ArrayB(1, 2, 3); assert(myArrB instanceof Array)&lt;/span&gt;&quot;. The dual problem examined in my post is where an instance of a class must be made reactive (&quot;&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;var myArr = [1,2,3]; ...; var myArrB = bindB(myArr)&lt;/span&gt;&quot;). It is an important practical distinction because the developer writing &quot;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;var myArrB = bindB(myArr)&lt;/span&gt;&quot; might not have control over &quot;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;var myArr = [1,2,3]&lt;/span&gt;&quot; nor &quot;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;.&lt;/span&gt;&quot;.&lt;br /&gt;
&lt;br /&gt;
His connection is important for two reasons: it provides a principle for how bound arrays should act (as subclass instances) and, more generally, shows that the same approach can be used for making object instances reactive.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;1. Design principle of subclassing.&amp;nbsp;&lt;/i&gt;Given an array, his connection tells us that reactive version should act as a subclass of &lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Array&lt;/span&gt;. As seen above, this works for methods like &lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;push&lt;/span&gt; and [] (&lt;i&gt;get&lt;/i&gt;). However, the desired object protocol behavior is not obvious. For example, should &quot;&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;assert(myArrB instanceof Array)&lt;/span&gt;&quot; &amp;nbsp;succeed? By the subclass reasoning, yes!&lt;br /&gt;
&lt;br /&gt;
Unfortunately, setting&amp;nbsp;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;myArrB&amp;nbsp;&lt;/span&gt;to be an instance of Array breaks introspection within the Flapjax library. To add dependencies to an object, Flapjax checks whether it can register event listeners. For example, &quot;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;liftB(&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;function (v) { return v.length; },&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;myArrB&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;)&lt;/span&gt;&quot; triggers a check&amp;nbsp;&quot;&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;arg2 instanceof Behavior&lt;/span&gt;&quot;: if&amp;nbsp;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;myArrB &lt;/span&gt;is an Array and not a Behavior, Flapjax will not register listeners on it! Some examples still work, such as&amp;nbsp;&amp;nbsp;&quot;&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;myArrB.liftB(function (v) { return v.length; })&lt;/span&gt;&quot;, because the check is elided. For now, I support two constructor options:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;var xB = bindB(arr);&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;assert(xB instanceof Array); //indistinguishable from Array&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;xB.liftB(function (v) { return v.length; }); //only supports chained reaction&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;var yB = bindB(arr, true);&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;assert(xB instanceof Behavior); //distinguishable from Array&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;yB.liftB(function (v) { return v.length; }); //chained reactions&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;liftB(function (v) { return v.length; },&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;yB&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;); //and as arguments&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
The non-default constructor is more readily distinguished from an Array, and Flapjax uses this ability to &amp;nbsp;out-of-the-box to to react to it. If code consuming &quot;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;myArrB&lt;/span&gt;&quot; does not need &quot;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: xx-small;&quot;&gt;myArrB instanceof Array&lt;/span&gt;&quot;, I suggest the second, non-default form.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;2. Generalization to Objects. &lt;/i&gt;The motivation of this post was to handle array instances, but as Shriram implies, those are a special form of object instances. We get the simpler case of objects for free!&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;var o = {};&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;var p = bindB(o);&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;insertDomB(DIV(&quot;o has x: &quot;, p.liftB(function (v) { return v.x ? true : false; })));&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;//display shows false&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;p.x = 1; // o.x == 1 and display updates to show true&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;delete p.x; //o.x == undefined and display updates to show false&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The code snippet above shows creating a reactive view of an object. The original object is the backing store for the view, and edits to the reactive view automatically trigger DOM updates. As with arrays, when reactions occur can be controlled by choosing to edit the raw object or the view.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Conclusion&lt;/h3&gt;
&lt;br /&gt;
Via proxies, I was able to make imperative arrays play nicely along their &lt;i&gt;entire&lt;/i&gt;&amp;nbsp;API with our FRP library and support both instant and batched/transactional updates. &amp;nbsp;You can play with this in Firefox via my &lt;a href=&quot;http://jsfiddle.net/lmeyerov/v9SRR/&quot;&gt;JSFiddle&lt;/a&gt;. There is more to do (for example, the direct proxy API precludes behavioral indices &amp;nbsp;like fxArr[secondsB]), but the flexibility of this approach is handy.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
APPENDIX&lt;/h4&gt;
&lt;div&gt;
&lt;br style=&quot;color: #666666; font-family: Inconsolata, Monaco, Consolas, &#39;Andale Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, Courier, monospace; font-size: 12px; line-height: 15px;&quot; /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: xx-small;&quot;&gt;&lt;span class=&quot;js-keyword&quot; style=&quot;color: #770088; line-height: 15px;&quot;&gt;function&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-variable&quot; style=&quot;line-height: 15px;&quot;&gt;bindB&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-variabledef&quot; style=&quot;color: blue; line-height: 15px;&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-variabledef&quot; style=&quot;color: blue; line-height: 15px;&quot;&gt;asObj&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;)&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #88ff88; font-weight: bold; line-height: 15px;&quot;&gt;{&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-comment&quot; style=&quot;color: #aa7700; line-height: 15px;&quot;&gt;//Behavior prototype by default&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-keyword&quot; style=&quot;color: #770088; line-height: 15px;&quot;&gt;function&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-variabledef&quot; style=&quot;color: blue; line-height: 15px;&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-variabledef&quot; style=&quot;color: blue; line-height: 15px;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-variabledef&quot; style=&quot;color: blue; line-height: 15px;&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;)&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;{&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-keyword&quot; style=&quot;color: #770088; line-height: 15px;&quot;&gt;return&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-keyword&quot; style=&quot;color: #770088; line-height: 15px;&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;)&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-operator&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;==&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-string&quot; style=&quot;color: #aa2222; line-height: 15px;&quot;&gt;&#39;function&#39;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-operator&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;?&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-keyword&quot; style=&quot;color: #770088; line-height: 15px;&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;)&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;{&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-keyword&quot; style=&quot;color: #770088; line-height: 15px;&quot;&gt;return&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;js-property&quot; style=&quot;line-height: 15px;&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;}&amp;nbsp;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;:&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;}&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-keyword&quot; style=&quot;color: #770088; line-height: 15px;&quot;&gt;var&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-variabledef&quot; style=&quot;color: blue; line-height: 15px;&quot;&gt;resE&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-operator&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;=&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-variable&quot; style=&quot;line-height: 15px;&quot;&gt;receiverE&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-keyword&quot; style=&quot;color: #770088; line-height: 15px;&quot;&gt;var&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-variabledef&quot; style=&quot;color: blue; line-height: 15px;&quot;&gt;resB&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-operator&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;=&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;resE&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;js-property&quot; style=&quot;line-height: 15px;&quot;&gt;startsWith&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-keyword&quot; style=&quot;color: #770088; line-height: 15px;&quot;&gt;var&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-variabledef&quot; style=&quot;color: blue; line-height: 15px;&quot;&gt;protocol&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-operator&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;=&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;{&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-property&quot; style=&quot;line-height: 15px;&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;:&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-keyword&quot; style=&quot;color: #770088; line-height: 15px;&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-variabledef&quot; style=&quot;color: blue; line-height: 15px;&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-variabledef&quot; style=&quot;color: blue; line-height: 15px;&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-variabledef&quot; style=&quot;color: blue; line-height: 15px;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;)&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;{&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;]&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-operator&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;=&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;resE&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;js-property&quot; style=&quot;line-height: 15px;&quot;&gt;sendEvent&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-variable&quot; style=&quot;line-height: 15px;&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;,&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-property&quot; style=&quot;line-height: 15px;&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;:&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-keyword&quot; style=&quot;color: #770088; line-height: 15px;&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-variabledef&quot; style=&quot;color: blue; line-height: 15px;&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-variabledef&quot; style=&quot;color: blue; line-height: 15px;&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;)&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;{&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-keyword&quot; style=&quot;color: #770088; line-height: 15px;&quot;&gt;return&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;p&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-operator&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;==&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-string&quot; style=&quot;color: #aa2222; line-height: 15px;&quot;&gt;&quot;toSource&quot;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-operator&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;?&amp;nbsp;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;js-property&quot; style=&quot;line-height: 15px;&quot;&gt;toSource&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;)&amp;nbsp;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;:&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;resB&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;hasOwnProperty&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;)&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-operator&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;?&amp;nbsp;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;resB&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;]&amp;nbsp;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;:&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-variable&quot; style=&quot;line-height: 15px;&quot;&gt;Behavior&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;js-variable&quot; style=&quot;line-height: 15px;&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;hasOwnProperty&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;)&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-operator&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;?&amp;nbsp;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-variable&quot; style=&quot;line-height: 15px;&quot;&gt;Behavior&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;js-variable&quot; style=&quot;line-height: 15px;&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;resB&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;)&amp;nbsp;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;:&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;}&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-keyword&quot; style=&quot;color: #770088; line-height: 15px;&quot;&gt;return&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-keyword&quot; style=&quot;color: #770088; line-height: 15px;&quot;&gt;new&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-variable&quot; style=&quot;line-height: 15px;&quot;&gt;Proxy&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;asObj&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-operator&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;?&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;obj&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;:&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;resB&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot; style=&quot;color: #004499; line-height: 15px;&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #88ff88; font-weight: bold; line-height: 15px;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; line-height: 15px;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;font-size: xx-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;whitespace&quot; style=&quot;color: #666666; font-size: xx-small; line-height: 15px;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;js-keyword&quot; style=&quot;color: #770088; font-size: xx-small; line-height: 15px;&quot;&gt;var&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-variable&quot; style=&quot;font-size: xx-small; line-height: 15px;&quot;&gt;arr&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-operator&quot; style=&quot;color: #666666; font-size: xx-small; line-height: 15px;&quot;&gt;=&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; font-size: xx-small; line-height: 15px;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;js-string&quot; style=&quot;color: #aa2222; font-size: xx-small; line-height: 15px;&quot;&gt;&#39;init&#39;&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; font-size: xx-small; line-height: 15px;&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; font-size: xx-small; line-height: 15px;&quot;&gt;;&lt;/span&gt;&lt;br style=&quot;color: #666666; line-height: 15px;&quot; /&gt;&lt;span class=&quot;js-keyword&quot; style=&quot;color: #770088; font-size: xx-small; line-height: 15px;&quot;&gt;var&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-variable&quot; style=&quot;font-size: xx-small; line-height: 15px;&quot;&gt;fxArr&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-operator&quot; style=&quot;color: #666666; font-size: xx-small; line-height: 15px;&quot;&gt;=&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;js-variable&quot; style=&quot;font-size: xx-small; line-height: 15px;&quot;&gt;bindB&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; font-size: xx-small; line-height: 15px;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-variable&quot; style=&quot;font-size: xx-small; line-height: 15px;&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; font-size: xx-small; line-height: 15px;&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot; style=&quot;color: #666666; font-size: xx-small; line-height: 15px;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/7660801575260877723/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/7660801575260877723' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/7660801575260877723'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/7660801575260877723'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2012/12/mixing-functionalimperative-reactive.html' title='Reactive Objects and Arrays via Direct Proxies'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-7845714969033129711</id><published>2012-11-29T12:40:00.002-08:00</published><updated>2013-01-26T23:07:25.200-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="socio-plt"/><title type='text'>Google Tech Talk Video on Socio-PLT: Quantitative and Social Theories of Programming Language Adoption</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
My Google Tech Talk on the Socio-PLT work was recorded and posted. It starts with the quantitative stuff + questions on it, and then switches to the social theories: pick your poison.&amp;nbsp;Enjoy!&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;object class=&quot;BLOGGER-youtube-video&quot; classid=&quot;clsid:D27CDB6E-AE6D-11cf-96B8-444553540000&quot; codebase=&quot;http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0&quot; data-thumbnail-src=&quot;http://1.gvt0.com/vi/v2ITaI4y7_0/0.jpg&quot; height=&quot;266&quot; width=&quot;320&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/v2ITaI4y7_0&amp;fs=1&amp;source=uds&quot; /&gt;&lt;param name=&quot;bgcolor&quot; value=&quot;#FFFFFF&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&lt;embed width=&quot;320&quot; height=&quot;266&quot;  src=&quot;http://www.youtube.com/v/v2ITaI4y7_0&amp;fs=1&amp;source=uds&quot; type=&quot;application/x-shockwave-flash&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/7845714969033129711/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/7845714969033129711' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/7845714969033129711'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/7845714969033129711'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2012/11/google-tech-talk-video-on-socio-plt.html' title='Google Tech Talk Video on Socio-PLT: Quantitative and Social Theories of Programming Language Adoption'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-1995979060293577683</id><published>2012-11-28T11:42:00.005-08:00</published><updated>2013-01-26T23:07:35.390-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="flapjax"/><title type='text'>Temp URLs for Flapjax documentation</title><content type='html'>The Flapjax server is a bit wonky right now, so if you are looking for online documentation, check out the following:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://webcache.googleusercontent.com/search?q=cache:XUANgrdCLJIJ:www.flapjax-lang.org/docs/+&amp;amp;cd=1&amp;amp;hl=en&amp;amp;ct=clnk&amp;amp;gl=us&quot;&gt;google cache of current docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.eecs.berkeley.edu/~lmeyerov/projects/flapjax/docs/index.html&quot;&gt;new docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Of course, you can always check the &lt;a href=&quot;https://github.com/brownplt/flapjax&quot;&gt;git repo&lt;/a&gt; for the latest.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Hope that helps!&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/1995979060293577683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/1995979060293577683' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/1995979060293577683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/1995979060293577683'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2012/11/temp-urls-for-flapjax-documentation.html' title='Temp URLs for Flapjax documentation'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-1586115978738928734</id><published>2012-11-22T13:34:00.004-08:00</published><updated>2013-01-26T23:07:44.086-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="socio-plt"/><title type='text'>What Women Want</title><content type='html'>&lt;a href=&quot;http://www.quora.com/Computer-Programming/Which-programming-language-is-the-most-female-friendly&quot;&gt;Trending on Quora&amp;nbsp;&lt;/a&gt;is the question, &quot;Which programming language is the most female friendly?&quot;I do not know (I can provide primary sources who will verify this), but based on our survey of 802 men and 154 women, I can answer which languages females prefer over males.&amp;nbsp;To learn how to think about these questions, see my recent&amp;nbsp;&lt;a href=&quot;http://www.youtube.com/watch?v=v2ITaI4y7_0&quot;&gt;Google Tech Talk&lt;/a&gt;&amp;nbsp;or the links below.&lt;br /&gt;
&lt;br /&gt;
Gayle presciently suggests that &quot;Python is also a no-no because, I mean, you just named a language after a snake. Ick! And, I mean, do I need to call out the Freudian imagery there?&quot; Go Gayle -- there is indeed a 3% drop!&amp;nbsp;However, despite Gayle&#39;s insight that &quot;All women love shiny objects,&quot; that does not help Ruby. Our numbers show a 7% drop for Ruby, so Ruby&#39;s&amp;nbsp;&lt;a href=&quot;http://martinfowler.com/bliki/SmutOnRails.html&quot;&gt;bad press&lt;/a&gt;&amp;nbsp;might be representative.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJN5ZMQ-WkZNsy-I_i2359zn9CvonnlRswllnw1KpQdGTCZEY5SKLxLBQ2P8di3w-po26uuEkB1JpN5FjmtwxwZMQYbOdsPtCn2A0z2WcGeXCAEUHTDi_LWMUcCrckTtdBDcnXyXPgmpk/s1600/stats.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;271&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJN5ZMQ-WkZNsy-I_i2359zn9CvonnlRswllnw1KpQdGTCZEY5SKLxLBQ2P8di3w-po26uuEkB1JpN5FjmtwxwZMQYbOdsPtCn2A0z2WcGeXCAEUHTDi_LWMUcCrckTtdBDcnXyXPgmpk/s400/stats.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Overall, we saw little difference among the top 10 languages known by males and females. The ordering is fairly stable, and overall knowledge is similar (see the pink trendline). A few language jumps stand out: C, PHP, C#, and Ruby drop for female knowledge, while &amp;nbsp;Excel rises.&lt;br /&gt;
&lt;br /&gt;
&lt;br class=&quot;Apple-interchange-newline&quot; /&gt;
If you&#39;re curious, check out our&amp;nbsp;&lt;a href=&quot;http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/papers/plateau2012.pdf&quot;&gt;methodology&lt;/a&gt;, more of our&amp;nbsp;&lt;a href=&quot;http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/papers/icse13b.pdf&quot;&gt;statistics&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href=&quot;http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/data/all.tar.gz&quot;&gt;raw data&lt;/a&gt;, and what a language designed for women&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/L%C3%A1adan&quot;&gt;might look like&lt;/a&gt;. Long story short, for the above statistics, we had good respondents: mostly educated, mostly employed, and biases because we polled students taking a free UC Berkeley online Ruby course on software as a service.</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/1586115978738928734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/1586115978738928734' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/1586115978738928734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/1586115978738928734'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2012/11/what-women-want.html' title='What Women Want'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJN5ZMQ-WkZNsy-I_i2359zn9CvonnlRswllnw1KpQdGTCZEY5SKLxLBQ2P8di3w-po26uuEkB1JpN5FjmtwxwZMQYbOdsPtCn2A0z2WcGeXCAEUHTDi_LWMUcCrckTtdBDcnXyXPgmpk/s72-c/stats.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-1506498498250841429</id><published>2012-11-03T21:00:00.000-07:00</published><updated>2013-01-26T23:08:08.585-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="parallel browser"/><category scheme="http://www.blogger.com/atom/ns#" term="synthesis"/><title type='text'>Asymptotic Productivity of a Language Feature</title><content type='html'>Good news: our big data visualization DSL has a new name (Superconductor!), runs in a browser, and even more unusual, &lt;i&gt;a per-feature asymptotic analysis&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
We built a synthesizer for Superconductor that automatically maps widget code down into parallel algorithms, but synthesis isn&#39;t magic: the more you want it to do, the longer it has to run. Synthesis is essentially a search that automates manual thinking a programmer would have performed. This introduces a new way of thinking about the benefit of language features. Features have a cost, and instead of being in runtime complexity, it is now in compilation speed, which is arguably a formal proxy for developer time. The new language design question is how to tame these costs by isolating them, and when pricey features are still desirable, how to provide levers.&lt;br /&gt;
&lt;br /&gt;
Consider two of the following features in our language:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Automatic full tree traversals.&amp;nbsp;&lt;/b&gt;For a particular top-down parallel traversal over a document, what parts of the (declarative) computation can be safely mapped into it? Not forcing the programmer to figure this out ends up being O(A^2) in the number of static object fields being computed. It took a bit of work (iterative refinement and topological sorting), but well worth it!&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Automatic subtree traversals. &lt;/b&gt;Sometimes, different parts of a tree have different types of data dependencies. For example, text in CSS is represented as a subtree of the document, and several computations over it are inherently sequential such as line wrapping. The tree traversal that encounters text does not need to be sequential, however: for each traversal, we can run different types of subtrees with different types of traversals, and thereby exploit parallelism within some subtrees and even by running disjoint subtrees concurrently. The feature to automatically infer subtree traversals blows up in the number of types of nodes (classes). Basically, each partitioning of the classes is a different way of statically characterizing a different subtree (and matched with a traversal type, a prospective parallelization scheme).&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
Synthesis is fast enough that automatic parallelization of full tree traversals are effectively free. However,&amp;nbsp;specializing for per-subtree traversal schedules is only fast for programs with few types of nodes. Subtree traversals are useful in practice (such as if you enjoy stylized text on a webpage!), so we still need to support it. What is a language designer to do?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Deprioritization. Of parallelization can occur without using a slow feature, it will. In this case, the search will look for a full tree traversal before trying subtree ones. O(A^2) asymptotics are actually preserved, even if the full tree traversal is impossible: if there is no full tree traversal, we guarantee there is no subtree traversal, and therefore can stop compilation and terminate with an error. Enumerating all parallelizations will reveal a subtree traversal if it exists, this will not be exercised during most development.&lt;/li&gt;
&lt;li&gt;Sketching. We use sketching for targeted opt-in prioritization of slow features. If you know the third tree traversal of the algorithm should use subtree traversals, say so, and even better, give a hint as to how to group the classes. If you do that, synthesis will still handle mapping individual computations into the traversals, including the subtree ones, and compilation is still O(A^2)!&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;br /&gt;
Asymptotics of synthesis is an intriguing way to characterize language features, and perhaps a step towards representing developer effort. It defines how much is &#39;unsaid&#39; in a precise way, how hard is the &#39;exercise for the reader&#39;. There is still more to be desired -- the asymptotics is subject to the synthesis algorithm and translation of the features into it -- but I found it to be a neat, and an insightful indicator for productivity.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/1506498498250841429/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/1506498498250841429' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/1506498498250841429'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/1506498498250841429'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2012/11/asymptotic-productivity-of-language.html' title='Asymptotic Productivity of a Language Feature'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-339997137263113605</id><published>2012-08-31T09:17:00.005-07:00</published><updated>2013-01-26T23:08:19.449-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="socio-plt"/><title type='text'>Quantifying Social Influences on Language Adoption</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfAmQgsd_fM3i6S0e-RknOmJaRyqlQuLqp-U3crMaPqaw-r0iwO66LiI4Ko9OMbrslCVbUkox4pzA59cQsCj0Nlh_MAM9PxkiOQqN_D0j597DdQGACQR9zfostR-8UCugprbo_Zaj5V5E/s1600/features.tiff&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;br class=&quot;Apple-interchange-newline&quot; /&gt;&lt;span id=&quot;goog_47211661&quot;&gt;&lt;/span&gt;&lt;span id=&quot;goog_47211662&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjum4cxR_KFklIBiKB_Jdg0J4c6I0mZea5fFbV-gSVu5BFIlvHHbQ65ku87P0ax_N7sf_D3-j7bAdDWR1yh_IQTpZEugOTBQKN5pnPfs7ZG6eqo5FbFEo6jj4SO90frEt4A4reYg9DoPC4/s1600/features.tiff&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em; text-align: center;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;218&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjum4cxR_KFklIBiKB_Jdg0J4c6I0mZea5fFbV-gSVu5BFIlvHHbQ65ku87P0ax_N7sf_D3-j7bAdDWR1yh_IQTpZEugOTBQKN5pnPfs7ZG6eqo5FbFEo6jj4SO90frEt4A4reYg9DoPC4/s640/features.tiff&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;b&gt;Average influences for picking a language at work&lt;/b&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
As alluded to in the previous post, Ari and I have been hard at work at quantitatively analyzing how programming languages get adopted &amp;nbsp;-- or fail to. &amp;nbsp;For example, the above chart shows that for commercial projects, &amp;nbsp;social factors (open source libraries, legacy code, and familiarity) matter much more than language support (correctness, simplicity, development speed, tools, language features, ...). This chart is also fascinating because we see that developers act differently depending on the company size.&lt;br /&gt;
&lt;br /&gt;
Check out &lt;a href=&quot;http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/papers/icse13.pdf&quot;&gt;our draft &quot;Social Influences on Language Adoption&quot;&lt;/a&gt;&amp;nbsp;for more fun charts where we performed and analyzed large surveys and also looked at 10 years of the SourceForge repository with over 200,000 projects. As another example, we validated some of our suspicions in the &lt;a href=&quot;http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/papers/onward2012.pdf&quot;&gt;sociology survey&lt;/a&gt; that DSLs can be understood in terms of competing niches (e.g., popularity comes from spreading to other niches, not being the best in the niche). We&#39;d love comments! More is in the pipeline -- we&#39;ll be releasing the raw data and also a small writeup about the methodological hazards we had to circumvent for this type of research.</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/339997137263113605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/339997137263113605' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/339997137263113605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/339997137263113605'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2012/08/quantifying-social-influences-on.html' title='Quantifying Social Influences on Language Adoption'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjum4cxR_KFklIBiKB_Jdg0J4c6I0mZea5fFbV-gSVu5BFIlvHHbQ65ku87P0ax_N7sf_D3-j7bAdDWR1yh_IQTpZEugOTBQKN5pnPfs7ZG6eqo5FbFEo6jj4SO90frEt4A4reYg9DoPC4/s72-c/features.tiff" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-2874124168593444022</id><published>2012-07-27T16:22:00.002-07:00</published><updated>2013-01-26T23:08:29.766-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="socio-plt"/><title type='text'>Socio-PLT camera-ready and a glimpse at the next step</title><content type='html'>Our Onward! 2012 draft about matching problems in programming languages to social theories about adoption made a stir -- and &lt;a href=&quot;http://lmeyerov.blogspot.com/2012/06/socio-plt-quantifying-language.html&quot;&gt;solicited some great comments&lt;/a&gt;. We&#39;re cleaning up the &lt;a href=&quot;http://www.cs.princeton.edu/~asrabkin/papers/onward12.pdf&quot;&gt;camera ready&lt;/a&gt;, so if there are any final comments, we&#39;d love to incorporate them for the &#39;final&#39; print version. It&#39;s a controversial topic!&lt;br /&gt;
&lt;br /&gt;
As a follow-up, we&#39;ve been doing some heavy quantitative analysis of extrinsic (social) and intrinsic factors in language adoption. &amp;nbsp;These charts should give you a taste:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://i.imgur.com/SZSzE.png?1&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;146&quot; src=&quot;http://i.imgur.com/SZSzE.png?1&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;b&gt;Fig 1: Factors in Picking a Language for A Recent Project&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://i.imgur.com/3XDYv.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;218&quot; src=&quot;http://i.imgur.com/3XDYv.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;b&gt;Fig 2:&lt;/b&gt;&amp;nbsp;&lt;b&gt;Language Popularity on SourceForge&lt;/b&gt;.&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
The first figure is cool in that it shows that social factors are more important than intrinsic features when picking a language. &lt;i&gt;Language designers are community builders.&lt;/i&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
The second figure starts questioning the social structure. Popularity, city populations, etc. often follow power laws, and therefore growth gets modeled by some intuitive generative processes. However, SourceForge for ~200,000 projects followed an exponential curve. What type of processes can make more sense there?&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
Anyways, hope the&amp;nbsp;&lt;a href=&quot;http://www.cs.princeton.edu/~asrabkin/papers/onward12.pdf&quot;&gt;camera ready&lt;/a&gt;&amp;nbsp;&lt;span style=&quot;background-color: white;&quot;&gt;looks good and the quantitatve analysis sparks thought :)&lt;/span&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/2874124168593444022/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/2874124168593444022' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/2874124168593444022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/2874124168593444022'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2012/07/socio-plt-camera-ready-and-glimpse-at.html' title='Socio-PLT camera-ready and a glimpse at the next step'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-5701130968666625904</id><published>2012-07-06T11:54:00.002-07:00</published><updated>2013-01-26T23:08:41.978-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="parallel browser"/><category scheme="http://www.blogger.com/atom/ns#" term="synthesis"/><title type='text'>Synthesis over Parallel Patterns: A Leap Beyond Parallel Frameworks, Types, and Annotations</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipq6tD0cMp9Ck_9HAZPmvTRHIFxkB5c2IRqGFUfsXUeowkwU3lVjcgsgrtsgI4b5ijjufn1AZPn592cCQdweRqakUxaA6wlusVwU0mtHKLOHfvOBTBJr25AIFvZKmR99_-628jpqujbNo/s1600/about.tiff&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;138&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipq6tD0cMp9Ck_9HAZPmvTRHIFxkB5c2IRqGFUfsXUeowkwU3lVjcgsgrtsgI4b5ijjufn1AZPn592cCQdweRqakUxaA6wlusVwU0mtHKLOHfvOBTBJr25AIFvZKmR99_-628jpqujbNo/s320/about.tiff&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
We&#39;ve been struggling with explaining the theoretical PL parts of our language research, but I think we&#39;re finally circling in. Basically, we found attribute grammars OK for defining the functional behavior of CSS and simple enough for running basic compiler analyses, but the formalism is poor for programming over the parallel patterns used for efficient runtime evaluation. That&#39;s where our language extensions for synthesizing over parallel patterns comes in.&lt;br /&gt;
&lt;br /&gt;
Synthesizing over / into parallel patterns breaks down to three high-level issues:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;b&gt;The low-level language of patterns. &lt;/b&gt;&amp;nbsp;The low-level language has to thoroughly express how our crazy-optimized tree traversals can be used. Think of it as the assembly language for parallel algorithms.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;b&gt;The usable high-level language.&lt;/b&gt; Writing in assembly sucks. Unlike traditional higher-level languages, which suffer from &lt;a href=&quot;http://www.joelonsoftware.com/articles/LeakyAbstractions.html&quot;&gt;leaky abstractions&lt;/a&gt;, ours is a superset of the low-level one: you can always pick the right level. We do this by adding the simple notion of a&amp;nbsp;&lt;i&gt;hole.&amp;nbsp;&lt;/i&gt;Assemble the patterns where and how you want, but whatever patterns are inferable&amp;nbsp;or unimportant, just leave a hole and let the compiler figure it out.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;b&gt;The compilation technique&lt;/b&gt; for going from the high-level pattern language to the low-level one. I&#39;ll try to give a more detailed explanation in a future post. &amp;nbsp;In a sense, our algorithm is a form of &lt;a href=&quot;http://techreports.lib.berkeley.edu/accessPages/EECS-2008-176.html&quot;&gt;CEGIS&lt;/a&gt; (counter-example guided inductive synthesis) that searches over ways to complete a partial program. Every time there is a potential candidate, it checks if any input would trigger a bug in the candidate, and if so, prunes out this and any other completion with the same sort of breakage. Ours is a bit cooler than usual because we have a domain-specific constraint solver, use &lt;i&gt;symbolic&lt;/i&gt; counter examples ones that give asymptotic progress on the search, and we get a queryable debugger for free.&amp;nbsp;&lt;/span&gt;All for another day :)&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;First, however, a recap of our use of attribute grammars for the functional specification language, all of which sits besides the pattern specification language.&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;Background: Attribute Grammars&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
The functional behavior in our language is specified with attribute grammars. &amp;nbsp;For example, to define CSS, you&#39;ll say the width of an HBox is the sum of its children. That says nothing about when it is evaluated. Later, via our pattern specification layer, you can control that as well.&amp;nbsp;&lt;span style=&quot;background-color: white;&quot;&gt;In theory, other logical specification languages other than attribute grammars can be used, all the way up to your traditional favorite imperative language (see &lt;a href=&quot;http://people.csail.mit.edu/asolar/iap2009/&quot;&gt;Sketch&lt;/a&gt;). However, the road from attribute grammars is clear, with most other alternative surface layers adding a painful indirection.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
A traditional attribute grammar would let you declaratively define the horizontal box layout widget as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;
HBox -&amp;gt; Node Node 
{ HBox.width := max(HBox0.minWidth, Node1.width + Node2.width); ... }
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Under our extensions (object-orientation, loops, etc.), we would instead write:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;
class HBox (paintRect) : Node
&amp;nbsp; attributes:
&amp;nbsp; &amp;nbsp; input minWidth
&amp;nbsp; &amp;nbsp; var intrinsWidth
&amp;nbsp; children:
&amp;nbsp; &amp;nbsp; childs : [ Node ]
&amp;nbsp; constraints
&amp;nbsp; &amp;nbsp; width = max(minWidth, intrinsWidth)
&amp;nbsp; &amp;nbsp; loop childs:
&amp;nbsp; &amp;nbsp; &amp;nbsp; intrinsWidth = fold 0 .. childs[i - 1].width&lt;/div&gt;
&lt;br /&gt;
Hopefully the mapping is intuitive. Our extensions are nice, for example, because we support lists of children. Instead of making an awkward NodeList tree schema with a traditional grammar, you can just have a list of Nodes (&quot;childs : [Node]&quot;) in our modernized form (think EBNF). &amp;nbsp;&lt;span style=&quot;background-color: white;&quot;&gt;In the end, after some compiler translation, it&#39;s the same thing. After reductions, traditional AG compiler checks ensure that every variable is assigned exactly once (well-defined and non-ambiguous spec) and can generate a schedule that orders the assignments. Code generation (e.g., of a layout engine) is a direct step after getting the schedule. &amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;In the example, our compiler realizes the width of an HBox should be computed after the loop. More subtle, when and how to perform the loops is determined as well. For example, this grammar defines a tree where some nodes have interface Node, such as HBox ones. The width of these nodes will be computed in a bottom-up or inorder traversal over the entire tree: for an inorder traversal, the compiler would insert a &quot;recur&quot; right before the computation of &quot;intrinsWidth.&quot; Writing loopy code in our language is cathartic for this reason. You just say a statement occurs in some loop, and the compiler will figure out in which loop and when, and reason about both local loops over the children of a node and global loops over the tree.&amp;nbsp;&lt;/span&gt;
&lt;br /&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;&lt;br class=&quot;Apple-interchange-newline&quot; /&gt;To learn more about attribute grammars and our use of them for layout language specifications, I previously wrote about our&amp;nbsp;&lt;a href=&quot;http://lmeyerov.blogspot.com/2012/03/declarative-loops-or-functional-isnt.html&quot;&gt;declarative looping construct&lt;/a&gt;&amp;nbsp;and an early experience in&amp;nbsp;&lt;a href=&quot;http://lmeyerov.blogspot.com/2012/03/modeling-language-experience-report.html&quot;&gt;mechanizing CSS&#39;s automatic table layout specification&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The Low-Level Pattern Language&lt;/b&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;Our conceptually deep extension really starts with being able to express this new fragment:&lt;/span&gt;&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;schedule:&lt;/span&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;&amp;nbsp; (bottomUp ((HBox (intrinsWidth width))) ) ; ??&lt;/span&gt;&lt;/div&gt;
I&#39;ll get into the &quot;??&quot; bit later, but some of the low-level language shows through here: a &lt;i&gt;bottomUp&lt;/i&gt;&amp;nbsp;(parallel postorder) tree traversal. Both bottom up and inorder tree traversals are valid passes for laying out any tree in this widget language, so our declarative pattern scheduling construct lets you pick which one. Most layout languages have many passes: if there was another class in this language, whatever pass comes after the semicolon would presumably handle whatever it needs to solve.&lt;br /&gt;
&lt;br /&gt;
Our schedules are expressive and fine-grained. The one above says exactly what attributes will be solved in the first bottomUp pass. Furthermore, the compiler will check that these attributes really will be solved in such a traversal. This is great if someone changes code elsewhere that has a non-local impact on the dependency structure, which is quite common in practice. The patterns can be complicated as well, such as using a (sequential) inorder traversal for some subtrees while doing an overall parallel bottom up, so help with reasoning about dependency validity is huge.&lt;br /&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;The amazing expressive bit about parallel pattern languages comes next, however.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;High-Level Pattern Language: Declarative Scheduling with Holes&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Imagine our HBox widget is being added to a parallel library. There might be some other traversals that happen after, but we want to guarantee that it will solve in the first one. The sequencing operator &quot;;&quot; runs one pattern after another. Powerfully, instead of saying what pattern to use next, we leave a hole, &quot;??&quot;. It might be instantiated as another pattern, say &quot;topDown&quot;, or even another composition of patterns, say &quot;topDown ; bottomUp&quot;. The synthesizer will figure out what is valid. These can quite non-obvious. For example, we repeatedly found inorder tree traversals that sequentialize a computation can often be eliminated. Instead, a global parallel (topdown or bottomup) traversal is run, and only certain &lt;i&gt;subtrees&lt;/i&gt; will be run as sequential &lt;i&gt;subtraversals&lt;/i&gt;. &lt;br /&gt;
&lt;br /&gt;
Holes can be anywhere (see the last line of the grammar above). If we don&#39;t care at all, we might replace the entire schedule with &quot;??&quot;. More commonly, we&#39;ll specify something like that a bottomUp should be first and then trust the synthesizer to compute the right attributes in it: &quot;(bottomUp ??) ; ??&quot;.&lt;br /&gt;
&lt;br /&gt;
Not shown in the grammar above, and generally only rarely exploited, arbitrary Prolog expressions can actually be used to constrain the holes. For example, the schedule may be one where the last traversal is an inorder one that makes sequential rendering calls. Writing &quot;?? ; (Inorder ??)&quot; is incorrect because it presupposes there is a preceding traversal. Prolog, for all its oddities, ended up being a great for such constraints.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Synthesizing over Parallel Patterns&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
The above declarative pattern language let&#39;s us automatically use efficient parallel patterns&amp;nbsp;with details where you care and holes where you don&#39;t. Synthesis over parallel patterns is powerful and expressive leap over say &quot;@parallel&quot; loop annotations in C++, map/reduce/etc. skeletons in cloud computing, and type-directed data parallelism in Haskell:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Our synthesizer&amp;nbsp;&lt;i&gt;finds&lt;/i&gt;&amp;nbsp;complicated parallel pattern usages. Not discussed, it doubles as a&amp;nbsp;&lt;i&gt;parallelism inspecter/debugger&lt;/i&gt;. (Topic for another day: the algorithms under the patterns, such as my cool &lt;i&gt;semi-static&lt;/i&gt;&amp;nbsp;extension to work stealing that gives temporal locality and drops overheads).&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;Our synthesizer&amp;nbsp;&lt;/span&gt;&lt;i style=&quot;background-color: white;&quot;&gt;automatically generates code&lt;/i&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&amp;nbsp;to exploit the parallelism based on an &lt;i&gt;orthogonal specification&lt;/i&gt;. No need to group code in the spec based on the parallelization scheme!&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Our low-level pattern language lets programmers&amp;nbsp;communicate&amp;nbsp;to&amp;nbsp;each other&amp;nbsp;and the&amp;nbsp;compiler&amp;nbsp;the &lt;i&gt;precise&lt;/i&gt; parallelization scheme.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Our&amp;nbsp;high-level pattern language (holes via synthesis) lets programmers communicate at an &lt;i&gt;arbitrarily high level.&lt;/i&gt;&amp;nbsp;Combined with the above, we get some very different styles of parallel programming: sometimes we roll in the mud, sometimes we don&#39;t.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: white;&quot;&gt;Our synthesizer &lt;/span&gt;&lt;i style=&quot;background-color: white;&quot;&gt;checks and&amp;nbsp;rejects&lt;/i&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&amp;nbsp;invalid schedules. This is good both when designing the initial code and especially essential when maintaining it. Editing someone else&#39;s parallel code is normally terrible: now we can both precisely learn about and check against the previous versions!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
It&#39;ll be fascinating to see if the community can get such &lt;i&gt;declarative schedule synthesis&lt;/i&gt;&amp;nbsp;for applying patterns beyond the tree traversal scenario. For example, I bet most graph computations (e.g., stencils) can have their level of abstraction similarly raised through our basic model.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/5701130968666625904/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/5701130968666625904' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/5701130968666625904'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/5701130968666625904'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2012/07/synthesis-over-parallel-patterns.html' title='Synthesis over Parallel Patterns: A Leap Beyond Parallel Frameworks, Types, and Annotations'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipq6tD0cMp9Ck_9HAZPmvTRHIFxkB5c2IRqGFUfsXUeowkwU3lVjcgsgrtsgI4b5ijjufn1AZPn592cCQdweRqakUxaA6wlusVwU0mtHKLOHfvOBTBJr25AIFvZKmR99_-628jpqujbNo/s72-c/about.tiff" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-6601689487423386994</id><published>2012-06-06T15:36:00.005-07:00</published><updated>2013-01-26T23:08:52.584-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="socio-plt"/><title type='text'>Socio-PLT: Quantifying Language Perception</title><content type='html'>We finally released our &lt;a href=&quot;http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/viz/index.html&quot;&gt;interactive visualizations for exploring programmer beliefs about programming languages&lt;/a&gt;. We&#39;ve been scouring several large data sets -- 10 years of SourceForge repo data, mass surveys of thousands of programmers each, etc. -- so visualizations like these help us get a grip on what&#39;s going on. Beyond revealing many surprises, such as static typing anti-correlating with code reuse, they are fun to play with.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/viz/index.html&quot;&gt;Check it out!&lt;/a&gt;&amp;nbsp;(Animations are fastest in Chrome/Safari)&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;img border=&quot;0&quot; height=&quot;281&quot; src=&quot;http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/viz/zoom.png&quot; width=&quot;320&quot; /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/6601689487423386994/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/6601689487423386994' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/6601689487423386994'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/6601689487423386994'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2012/06/socio-plt-quantifying-language.html' title='Socio-PLT: Quantifying Language Perception'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-2915586796249183033</id><published>2012-04-08T18:47:00.007-07:00</published><updated>2013-01-26T23:09:07.593-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="socio-plt"/><title type='text'>Socio-PLT: Principles for Programming Language Adoption</title><content type='html'>Ari and I are getting ready to send out our first paper on &lt;b&gt;&lt;i&gt;socio-PLT&lt;/i&gt;&lt;/b&gt;, the sociology of programming languages. We&#39;ve been performing qualitative and quantitative analysis of language adoption, and I&#39;ve been thinking about how to apply sociological principles to the design of my own languages. This paper 1) overviews some of my favorite cases that I gleaned from reviewing relevant sociology  research over the past few years and 2) connects it to programming language design, both in the scientific design of existing features and the principled and creative design of new ones. Basically, it shows how understanding results from sociology can influence your approach to language design :)&lt;br /&gt;
&lt;br /&gt;
I just &lt;a href=&quot;http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/paper0413.pdf&quot;&gt;put up a draft&lt;/a&gt; and would love comments. I suspect the paper may be controversial, but I would like it to be so for the right reasons :) Did we misrepresent anyone or leave out any awesome case studies? Was anything belabored and boring, or terse and tantalizingly vague? This is still in the draft state, so we have a lot to do and would appreciate feedback :)&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/paper0413.pdf&quot;&gt;&lt;b&gt;Socio-PLT: Principles for Programming Language Adoption&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;
&lt;blockquote&gt;
&lt;br /&gt;
Why does one programming language fail and another succeed? What does this tell us about programming language design, implementation, and principles? To help answer these and other questions, we argue for examining the sociological basis  of programming language theory: &lt;i&gt;socio-PLT&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
This paper presents a survey for programming language adoption principles drawn from various  sociological fields. For example, many programming language features provide benefits that programmers cannot directly and immediately observe and therefore may not find compelling. From clean water to safe sex, the health community has long examined how to surmount similar observability barriers. We discuss how principles and techniques drawn from social sciences such as economics, public health, and historical linguistics relate to programming languages. Finally, we examine implications of our approach, such as for the design space of language features and even the expectations of scientific research into programming languages.&lt;/blockquote&gt;
&lt;br /&gt;
&lt;br /&gt;
Looking forward to your thoughts! (&lt;a href=&quot;http://www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/paper0413.pdf&quot;&gt;draft pdf&lt;/a&gt;)</content><link rel="related" href="www.eecs.berkeley.edu/~lmeyerov/projects/socioplt/index.html" title="Socio-PLT: Principles for Programming Language Adoption"/><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/2915586796249183033/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/2915586796249183033' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/2915586796249183033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/2915586796249183033'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2012/04/socio-plt-principles-for-programming.html' title='Socio-PLT: Principles for Programming Language Adoption'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-2761097867189524420</id><published>2012-03-10T00:18:00.007-08:00</published><updated>2013-01-26T20:59:21.175-08:00</updated><title type='text'>Languages for Bad Programmers</title><content type='html'>&lt;i&gt;&lt;b&gt;Bad programmers are linguistic victims and good programmers are masochists.&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Brett Victor is going viral with an&amp;nbsp;&lt;a href=&quot;http://www.ritholtz.com/blog/2012/02/bret-victor-inventing-on-principle/&quot; style=&quot;font-family: Georgia, serif;&quot;&gt;inspiring video on language and tool design&lt;/a&gt; (and philosophy). The language community has actually already made some strong strides in the directions he wants. Some of my favorite research is in  &lt;a href=&quot;http://www.blogger.com/www.youtube.com/watch?v=faJ8N0giqzw&quot; style=&quot;font-family: Georgia, serif;&quot;&gt;tangible programming&lt;/a&gt;, &amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/Live_coding&quot; style=&quot;font-family: Georgia, serif;&quot;&gt;live coding&lt;/a&gt;, and &lt;a href=&quot;http://www.lambdacs.com/debugger/&quot;&gt;omniscient debuggers&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://patricklam.ca/&quot; style=&quot;font-family: Georgia, serif; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;&quot;&gt;Patrick Lam&lt;/a&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt; picked up on something else. As part of Brett Victor&#39;s philosophy that every code artifact should be directly (physically) manipulatable and understood, Brett believes requiring indirect manipulation and indirect understanding to be language design flaws. In particular, programming should not require mentally simulating an abstract Von Neumann machine that steps through your program. Not everyone agrees: Pat observed that, on the list of &lt;/span&gt;&lt;a href=&quot;http://badprogrammer.infogami.com/&quot; style=&quot;font-family: Georgia, serif; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;&quot;&gt;signs of being a bad programmer&lt;/a&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;, the very first warning that you are a bad programmer if you cannot &quot;run the program in your head&quot;. &lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Georgia, serif; font-weight: normal;&quot;&gt;Here&#39;s the thought. &lt;/span&gt;&lt;span style=&quot;font-family: Georgia, serif;&quot;&gt;&lt;b&gt;What would a language for bad programmers look like?&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Georgia, serif; font-weight: normal;&quot;&gt; Looking at the list of hacky &quot;bad&quot; programming practices, can you imagine a future where language and tool support will advance enough that they&#39;re the acceptable norm? &lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;The &quot;bad&quot; habits actually form an admirable set of goals for the language research community:&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Georgia, serif;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: red;&quot;&gt;Warning sign:&lt;/span&gt;&lt;/b&gt; Cannot simulate the program in their head.&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: blue;&quot;&gt;Goal:&lt;/span&gt; &lt;/b&gt;Get the computer to do the simulation.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Georgia, serif;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: red;&quot;&gt;Warning sign:&lt;/span&gt; &lt;/b&gt;Have a poor understanding of the language&#39;s programming model.&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: blue;&quot;&gt;Goal:&lt;/span&gt; &lt;/b&gt;If I make basic grammatical mistakes when I speak, people correct me -- why doesn&#39;t the compiler?&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Georgia, serif;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: red;&quot;&gt;Warning sign:&lt;/span&gt; &lt;/b&gt;Chronically poor knowledge of the platform&#39;s features. Symptoms: reinvent language and framework code, &quot;Email me teh code, plz&quot; messages on forums, etc. &lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: blue;&quot;&gt;Goal:&lt;/span&gt; &lt;/b&gt;Instead of viewing code copying as a bug, it&#39;s a design goal: I suspect *most* code today is duplicated, so I look forward to the future where the emphasis is on searching and synthesizing code rather than learning and writing it.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Georgia, serif;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: red;&quot;&gt;Warning sign:&lt;/span&gt; &lt;/b&gt;Struggle to comprehend pointers. Symptoms: failure to implement a linked list, allocates arbitrarily big arrays, inability to find pointer arithmetic bugs, etc. &lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: blue;&quot;&gt;Goal:&lt;/span&gt; &lt;/b&gt;raise the level of abstraction so programmers don&#39;t have to think about these issues.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Georgia, serif;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: red;&quot;&gt;Warning sign:&lt;/span&gt; &lt;/b&gt;Have difficulty seeing through recursion.&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: blue;&quot;&gt;Goal:&lt;/span&gt; &lt;/b&gt;Thinking concretely should be fine, and the tools should walk you through the base cases and generalization.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
You can apply similar reasoning to the category of &quot;mediocre programmers&quot; and, my favorite, &quot;pinball programmers&quot;. Pinball programmers struggle with edge cases, or simply do not care. They can be a security disaster.&lt;b&gt; Again, however.... so what? These types of problems are exactly what we built computers to solve: rote grunt work.&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-weight: normal;&quot;&gt;The shocking conclusion of the bad programmer essay is the signs that you shouldn&#39;t be a programmer. If you cannot determine the order of program execution, cannot think abstractly, poorly organize your code as an ever-expanding ball of mud, believe the code and runtime are unreliable, or simply don&#39;t care about much of the code quality, you shouldn&#39;t be a programmer. Hogwash!&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Georgia, serif;&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Georgia, serif;&quot;&gt;&lt;b&gt;If these traits are required for programming, our ability to write code that keeps growing in ambition by  magnitudes seems doomed&lt;/b&gt;. &lt;/span&gt;&lt;span style=&quot;font-family: Georgia, serif; font-weight: normal;&quot;&gt;I can fairly neatly bucket these warning signs as &lt;i&gt;inevitable programming realities&lt;/i&gt; (massive and concurrent code on unreliable hardware) and &lt;i&gt;goals&lt;/i&gt; (&quot;search, don&#39;t sort&quot;; declare what instead of how).&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
Maybe the programmers aren&#39;t really all that bad. It sounds like today&#39;s languages are the stupid ones.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(Updated 1/26/2013 with minor editing.)&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/2761097867189524420/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/2761097867189524420' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/2761097867189524420'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/2761097867189524420'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2012/03/languages-for-bad-programmers.html' title='Languages for Bad Programmers'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1440405560330732771.post-1536252878005933288</id><published>2012-03-07T20:57:00.004-08:00</published><updated>2013-01-26T23:09:29.650-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="parallel browser"/><category scheme="http://www.blogger.com/atom/ns#" term="synthesis"/><title type='text'>Loop synthesis: more declarative than functional programming?</title><content type='html'>As part of the FTL language, I&#39;ve been playing with the idea of declarative loops. For example, I&#39;d like to write:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;br /&gt;
for i in range(0, n):&lt;br /&gt;
b[i + 1] = g(a[i]); &lt;br /&gt;
a[i - 1] = f(b[i - 4]);&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
First, the synthesizer should figure out that the problem is under-constrained. It should report that the following values are undefined:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;br /&gt;
a[0..2] = ??&lt;br /&gt;
b[0] = ??&lt;br /&gt;
a[n] = ??&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
If, as suggested by the synthesizer, I refined the program to be consistent:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;br /&gt;
a[0..2] = 0&lt;br /&gt;
b[0] = 0&lt;br /&gt;
a[n] = 0&lt;br /&gt;
for i in range(0, n):&lt;br /&gt;
b[i + 1] = g(a[i]); &lt;br /&gt;
a[i - 1] = f(b[i - 4]);&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
I&#39;d like to get:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;br /&gt;
a[0] = 0&lt;br /&gt;
a[1] = 0&lt;br /&gt;
a[2] = 0&lt;br /&gt;
b[0] = 0&lt;br /&gt;
b[1] = g(a[0])&lt;br /&gt;
b[2] = g(a[1])&lt;br /&gt;
b[3] = g(a[2])&lt;br /&gt;
for (int i = 3; i &amp;lt; n - 1; i++) {&lt;br /&gt;
a[i] = f(b[i - 3]);&lt;br /&gt;
b[i + 1] = g(a[i])&lt;br /&gt;
a[n] = 0&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that the synthesizer performed loop peeling -- it figured out to do loop peeling to emit assignments for b[1], b[2], and b[3]. Furthermore, it reordered the assignments in the loop and performed loop skewing -- it changed the indices of the assignments, such as from a[i - 1] to a[i], to ensure an array value is written before it is read.&lt;br /&gt;
&lt;br /&gt;
Milind and I just worked out most of the theory for this today. You can think of it as a generalization of attribute grammar synthesis to loop code. Basically, if we assume the input code is singly assigned -- array values should have one unique value -- this is a matter of unrolling the intermediate steps of the loop, scheduling their dependency graph, and reconstructing the Von Neumann-friendly loop. The weekend may be busy :)&lt;br /&gt;
&lt;br /&gt;
A fun question is whether a functional program could declaratively handle the above. For example, it could expand the for loop into a dependency graph and then use demand-driven evaluation. However, there are two problems. First, the interpretation of indices would have to change: my code correctly skewed the loop indices to make sure &quot;a[i - 1]&quot; and &quot;b[i - 4]&quot; are never negative. Second, the loop would be unsafe: in my approach, the synthesizer can statically check that the array is fully defined. Either way, traditional functional languages force programmers to explicitly handle these (arguably) low-level loop details. Go synthesis!</content><link rel='replies' type='application/atom+xml' href='http://lmeyerov.blogspot.com/feeds/1536252878005933288/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1440405560330732771/1536252878005933288' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/1536252878005933288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1440405560330732771/posts/default/1536252878005933288'/><link rel='alternate' type='text/html' href='http://lmeyerov.blogspot.com/2012/03/declarative-loops-or-functional-isnt.html' title='Loop synthesis: more declarative than functional programming?'/><author><name>lmeyerov</name><uri>http://www.blogger.com/profile/05895714526572076172</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry></feed>