-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfeed.xml
803 lines (591 loc) · 126 KB
/
feed.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Jessica Rudder | software engineer, speaker, youtuber</title>
<description>Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.
</description>
<link>/</link>
<atom:link href="/feed.xml" rel="self" type="application/rss+xml"/>
<pubDate>Mon, 02 Apr 2018 20:02:47 -1000</pubDate>
<lastBuildDate>Mon, 02 Apr 2018 20:02:47 -1000</lastBuildDate>
<generator>Jekyll v3.6.2</generator>
<item>
<title>new way, new life</title>
<description><p>Today I choose life. Every morning when I wake up I can choose joy, happiness, negativity, pain… To feel the freedom that comes from being able to continue to make mistakes and choices.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sint libero, qui quos ducimus nemo deleniti veniam, nesciunt labore dicta saepe, et sequi repellendus minima fugit quisquam explicabo ab? Fuga, quo.</p>
<ul>
<li>A new command I give you: Love one another. As I have loved you, so you must love one another.</li>
<li>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</li>
</ul>
<p>Friends can help each other. A true friend is someone who lets you have total freedom to be yourself - and especially to feel. Or, not feel. Whatever you happen to be feeling at the moment is fine with them. That’s what real love amounts to - letting a person be what he really is.</p>
<blockquote>
<p>“Lorem ipsum dolor sit amet, consectetur adipisicing elit. Placeat assumenda amet nobis, laboriosam vel deleniti reprehenderit, molestias obcaecati, debitis inventore corporis illo nostrum id totam ea hic distinctio praesentium adipisci!””</p>
</blockquote>
<p>Keep love in your heart. A life without it is like a sunless garden when the flowers are dead. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eos, mollitia! Animi et dolore ab ratione cupiditate totam error ducimus, reiciendis voluptatum praesentium dignissimos vitae nostrum autem similique unde minus deleniti.</p>
</description>
<pubDate>Tue, 05 Apr 2016 12:48:03 -1000</pubDate>
<link>/travel/life/2016/04/05/new-way-new-life.html</link>
<guid isPermaLink="true">/travel/life/2016/04/05/new-way-new-life.html</guid>
<category>travel</category>
<category>life</category>
</item>
<item>
<title>new way, new move</title>
<description><p>Today I choose life. Every morning when I wake up I can choose joy, happiness, negativity, pain… To feel the freedom that comes from being able to continue to make mistakes and choices.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sint libero, qui quos ducimus nemo deleniti veniam, nesciunt labore dicta saepe, et sequi repellendus minima fugit quisquam explicabo ab? Fuga, quo.</p>
<ul>
<li>A new command I give you: Love one another. As I have loved you, so you must love one another.</li>
<li>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</li>
</ul>
<p>Friends can help each other. A true friend is someone who lets you have total freedom to be yourself - and especially to feel. Or, not feel. Whatever you happen to be feeling at the moment is fine with them. That’s what real love amounts to - letting a person be what he really is.</p>
<blockquote>
<p>“Lorem ipsum dolor sit amet, consectetur adipisicing elit. Placeat assumenda amet nobis, laboriosam vel deleniti reprehenderit, molestias obcaecati, debitis inventore corporis illo nostrum id totam ea hic distinctio praesentium adipisci!””</p>
</blockquote>
<p>Keep love in your heart. A life without it is like a sunless garden when the flowers are dead. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eos, mollitia! Animi et dolore ab ratione cupiditate totam error ducimus, reiciendis voluptatum praesentium dignissimos vitae nostrum autem similique unde minus deleniti.</p>
</description>
<pubDate>Tue, 05 Apr 2016 12:47:03 -1000</pubDate>
<link>/travel/2016/04/05/new-way-new-move.html</link>
<guid isPermaLink="true">/travel/2016/04/05/new-way-new-move.html</guid>
<category>travel</category>
</item>
<item>
<title>New Year's Resolutions</title>
<description><p>In general, I’m not big on New Year’s resolutions. I feel similar to the Stoics on this front - if there’s something that you truly want to change, change it. You don’t need an arbitrary time marker to make it happen. That said, there’s nothing more abitrary than a new year and I do like setting goals.</p>
<p>Last year I had two goals:</p>
<ol>
<li>Find a job I enjoy</li>
<li>Run every day for a year</li>
</ol>
<p>When I set the first goal, I imagined I’d be looking for a better situation in the same field - search engine marketing. I had been learning to code on the side for a couple years, but the goal of becoming a programmer seemed much further away. Through an odd sequence of events, I ended up taking the Web Development immersive at Flatiron School half-way through the year. Then I accepted a hybrid marketing/programming role at the school with the official title of Marketing Engineer (primarily so certain people could refer to me as a Marketeer).</p>
<p>Goal #1 was accomplished!</p>
<p>Sadly, Goal #1 killed Goal #2 as I threw myself into my new job. I had run a minimum of 1 mile (usually more) every day for the first 9.5 months of the year. I still ran most days, but, I missed 9 days in the final 2.5 months. Running 97.5% of the days in the year isn’t terrible.</p>
<p>That brings us to 2015.</p>
<p>More importantly, that brings us to this photo:</p>
<p><img class="img-center" src="/images/posts/2014-commits.png" width="737px" height="292px" alt="'jessrudder 2014 Commits'" title="My 2014 commits!" /></p>
<p>It’s my commit history on Github for 2014. Not bad, but I can do better. In fact, as a new developer, I need to do better. There are far too many stretches where no code is being written. So, I’m copying John Resig with his <a href="http://ejohn.org/blog/write-code-every-day/">Write Code Every Day</a> goal. I’d like to see a wall of green on my commit history at the end of 2015.</p>
<p>And, because I miss running (and I like to commit to doing things daily), I’m bringing back my 2014 goal of running every day for a year. In 2013 I only made it 6 months. In 2014 I made it 9.5. 2015 feels like my year!</p>
</description>
<pubDate>Thu, 01 Jan 2015 16:24:53 -1000</pubDate>
<link>/programming/flatiron-school/2015/01/01/new-years-resolutions.html</link>
<guid isPermaLink="true">/programming/flatiron-school/2015/01/01/new-years-resolutions.html</guid>
<category>programming</category>
<category>flatiron-school</category>
</item>
<item>
<title>AJAX - Get to Know Your Asynchronous Friend</title>
<description><p>AJAX! It’s a small acronoym for a heavy weight in the world of web development.</p>
<p>It stands for <strong>A</strong>synchronous <strong>J</strong>avascript <strong>a</strong>nd <strong>X</strong>ML. Which is a fancy way of saying that you can use Javascript and XML (and now JSON or even plain text) to send and receive data on a webpage without having to send the user to a new page or interrupt the activity on the current page.</p>
<p>Here’s an example of a simple AJAX call made in jQuery (taken from the <a href="http://en.wikipedia.org/wiki/Ajax_\(programming\)">AJAX wikipedia page</a>):</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">$</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="s1">'send-ajax-data.php'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>Let’s follow this AJAX call on it’s journey through the stack:</p>
<ol>
<li>The visitor initially comes to the page where the jQuery is hanging out</li>
<li>The jQuery code is activated (usually when the page loads or a button is pressed depending on how the code is written)</li>
<li>A GET request is sent to the ‘send-ajax-data.php’ page using an XMLHttpRequest object (which is what allows the request to be made asynchronously)</li>
<li>The ‘send-ajax-data.php’ page receives the request and sends a response as XML, JSON, a Javascript file or plain text</li>
<li>The initial page the visitor is on opens an alert window which displays the data it received as a response</li>
</ol>
<p>Thanks to the XMLHttpRequest object, this is all done behind the scenes while the visitor is still able to interact with the initial page that they are on.</p>
<p>Here’s a bit more complex example from a recent project I worked on. The AJAX call hits the Weather Underground hourly data page for NY and returns a JSON object with a ton of data including the temperature, the UV index, wind speed/direction and more.</p>
<p>I parse that data in the sucess callback, pulling out only what I need for my project. This data is then used (in a non-excerpted part of the code) to make an hourly graph of the temperature for the past 24 hours.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
<span class="na">url</span><span class="p">:</span> <span class="s2">"http://api.wunderground.com/api/API_KEY/hourly/q/NY/New_York.json"</span><span class="p">,</span>
<span class="na">dataType</span><span class="p">:</span> <span class="s1">'jsonp'</span><span class="p">,</span>
<span class="na">success</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">weather_data_full</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">weather_data_parsed</span> <span class="o">=</span> <span class="nx">weather_data_full</span><span class="p">[</span><span class="s1">'hourly_forecast'</span><span class="p">],</span>
<span class="nx">hourData</span> <span class="o">=</span> <span class="p">[],</span>
<span class="nx">tempData</span> <span class="o">=</span> <span class="p">[],</span>
<span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="nx">$</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">weather_data_parsed</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">hourData</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">weather_data_parsed</span><span class="p">[</span><span class="nx">i</span><span class="p">][</span><span class="s1">'FCTTIME'</span><span class="p">][</span><span class="s1">'hour'</span><span class="p">]),</span>
<span class="nx">tempData</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">weather_data_parsed</span><span class="p">[</span><span class="nx">i</span><span class="p">][</span><span class="s1">'temp'</span><span class="p">][</span><span class="s1">'english'</span><span class="p">]);</span>
<span class="nx">i</span><span class="o">++</span><span class="p">;</span>
<span class="p">});</span>
</code></pre></div></div>
<p>As you can see, there’s more going on, but, at it’s core, it’s the same as the simpler AJAX request above.</p>
<p>AJAX is definitely useful, but I don’t want to pretend it’s all sunshine and roses. This isn’t the first technology in history that magically has no tradeoffs. Here are some of the issues you should consider when deciding whether or not to utilize AJAX:</p>
<ul>
<li>
<p>Things are happening on a single page so there are no permalinks people can use for bookmarking that specific content on your site. <strong>PJAX</strong> attempts to address this by providing permalink functionality to AJAX requests, but AJAX itself won’t cut it.</p>
</li>
<li>
<p>The asynchronisity that makes AJAX so awesome and useful also makes it very hard to test and debug when something goes wrong. When lines of code are executed in a nice, clean order, it’s easier to track down the issue. AJAX does what it wants, when it wants (not exactly, but you get the idea). Did something break because the AJAX request isn’t correct? Because the AJAX fired too soon? Because the AJAX fired too late? Because of something not at all related to the AJAX and you need to stop blaming Javascript for everything??!? Have fun spending the next 5 hours of your life figuring that one out.</p>
</li>
<li>
<p>Web crawlers usually ignore javascript (and flash and anything else besides text and HTML you’ve added to your site to make it interesting). If you’re loading key content through AJAX, the crawler won’t see it unless you provide it with an alternative way to get that content. You can pretend you’re too cool for webcrawlers, but, at the end of the day, if you’re not aready a hot destination on the internet, you’ll need search engines to bring you traffic.</p>
</li>
</ul>
<p>What interesting uses of AJAX have you seen? Have you had any hilarious (or frustrating) AJAX experiences (like Catherine with her <a href="http://anunexpectedcoder.com/blog/2014/08/10/premature-ajaxulation/">Premature AJAXulation</a>)? Let me know in the comments!</p>
</description>
<pubDate>Thu, 28 Aug 2014 12:33:35 -1000</pubDate>
<link>/ajax/xml/json/2014/08/28/ajax-get-to-know-your-asynchronous-friend.html</link>
<guid isPermaLink="true">/ajax/xml/json/2014/08/28/ajax-get-to-know-your-asynchronous-friend.html</guid>
<category>ajax</category>
<category>xml</category>
<category>json</category>
</item>
<item>
<title>A Tale of Two Georges: Refactoring History with the N+1 Problem</title>
<description><p>The lower Manhattan ‘hood of the Flatiron School is steeped in history. But not just any history - Revolutionary History. And, as any red-blooded American with a patriotic tattoo will attest, there is no more historicky history than that because…<strong>‘Murica</strong>.</p>
<p><img class="img-center" src="/images/posts/murica.jpg" width="500px" height="900px" alt="'Murica'" title="Murica" /></p>
<p>The date is July 9, 1776. Tension has been rising between Great Britain and the colonies over critical issues like taxes, tea and how to spell color. <img class="img-right" src="/images/posts/statue-w-speech.png" width="400px" height="750px" alt="'King George and His Statue'" title="Artist Rendition of Statue of King George" /> The epicenter of much of this tension is Bowling Green park. Six years earlier, a 4,000 pound statue of King George astride a horse in Roman garb had been erected in the park. This proved to be too large of a target for the local rabble who couldn’t resist vandalizing the statue on their way home from their nightly pub crawls. In response, the government passed anti-vandalism laws and surrounded the park with a cast iron fence. That fence looks a lot like the one that’s there today - but newer - about 241 years newer.</p>
<p>Now, in July of 1776, war is imminent. The British are amassing a force of redcoats and Hessian mercenaries on Staten Island in preparation for an invasion (proving that even back then, nothing good came from Staten Island). George Washington addresses a crowd that has gathered in front of City Hall. “Yo! We’ve dissolved the connection between this country and Great Britain. The United Colonies of North America are now free and independent states.” Then he read the Declaration of Independence.</p>
<p>These days, we yawn when someone starts blathering on about the Declaration, but back then, it was exciting. The crowd was pumped and needed to do something to celebrate their new freedom. RIOT!!! So they stormed down to Bowling Green, tore down the statue of King George, paraded the head around on a pike and sent the rest to Connecticut to be made into musket balls.</p>
<p>Things were about to get real!</p>
<p>As you can imagine, King George did not appreciate the desecration of his statue and he was pretty sure it was a violation of the anti-vandalism laws passed three years earlier. He knew it was time for a colonial beat down. The king was a planner though and he wanted to make sure his Army was ready for the task ahead of them.</p>
<p>“Smythe!” he bellowed in a kingly fashion. “Gather the troops. Once they’re gathered, poll each of them to find out where they are currently stationed.”</p>
<p>Smythe was an extremely forward-thinking fellow and decided to build a Rails app with ActiveRecord in order make the data as accessible as possible to the king.</p>
<p>His models looked a little something like this:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#in the models</span>
<span class="c1">#Soldier model</span>
<span class="k">class</span> <span class="nc">Soldier</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span>
<span class="n">belongs_to</span> <span class="ss">:unit</span>
<span class="k">end</span>
<span class="c1">#Unit model</span>
<span class="k">class</span> <span class="nc">Unit</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span>
<span class="n">has_many</span> <span class="ss">:soldiers</span>
<span class="k">end</span>
</code></pre></div></div>
<p>While he was forward-thinking, Smythe wasn’t too database savvy and he set up his controllers and view like this.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#in the controller</span>
<span class="vi">@royal_army</span> <span class="o">=</span> <span class="no">Soldier</span><span class="p">.</span><span class="nf">all</span>
<span class="c1">#in the view</span>
<span class="vi">@royal_army</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">soldier</span><span class="o">|</span>
<span class="no">Name</span><span class="p">:</span> <span class="o">&lt;</span><span class="sx">%= soldier.name %&gt;
Location:&lt;%=</span> <span class="n">soldier</span><span class="p">.</span><span class="nf">unit</span><span class="p">.</span><span class="nf">location</span> <span class="sx">%&gt;
end
</span></code></pre></div></div>
<p>On the first call to the database, Smythe’s program gathers all the soldiers. However, it has to make another call to the database for every single soldier in order to determine the soldier’s location. For those of you keeping track, that’s N + 1 calls to the database, and, given the latency of databases in 1776, that’s a problem.</p>
<p>The app will definitely work, but it could be a long time before the king has the data he needs.</p>
<p><img class="img-left" src="/images/posts/gw-w-speech.png" width="450px" height="825px" alt="'Statue of George Washington with Speech Bubble'" title="N+1 is N+Nothing to the General" /> General Washington was also sure that war was imminent. Mobs don’t tear down statues and turn them into 42,088 ‘patriot bullets’ without intending to use them. Like King George, George Washington wanted to make sure that his army was ready to fight.</p>
<p>“Smith!” he said in a very general-esque fashion, “Gather the troops. I need some information from them.” Smith started to leave when the general (a man with legendary critical thinking skills) called him back. “Smith…when you gather the troops, it’s probably a good idea for you to grab their unit data too. That way we can easily find out where they are currently stationed without using up too much extra time.”</p>
<p>Smith (like Smythe) was a very forward-thinking fellow and decided to build a Rails app of his own. As you can imagine, their models were identical:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#in the models</span>
<span class="c1">#Soldier model</span>
<span class="k">class</span> <span class="nc">Soldier</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span>
<span class="n">belongs_to</span> <span class="ss">:unit</span>
<span class="k">end</span>
<span class="c1">#Unit model</span>
<span class="k">class</span> <span class="nc">Unit</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span>
<span class="n">has_many</span> <span class="ss">:soldiers</span>
<span class="k">end</span>
</code></pre></div></div>
<p>But when he made his controller, Smith followed the general’s sage advice and used eager loading.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#In our controller</span>
<span class="vi">@continental_army</span> <span class="o">=</span> <span class="no">Soldier</span><span class="p">.</span><span class="nf">includes</span><span class="p">(</span><span class="ss">:unit</span><span class="p">).</span><span class="nf">all</span>
<span class="c1">#in our view file</span>
<span class="vi">@continental_army</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">soldier</span><span class="o">|</span>
<span class="no">Name</span><span class="p">:</span> <span class="o">&lt;</span><span class="sx">%= soldier.name %&gt;
Location:&lt;%=</span> <span class="n">soldier</span><span class="p">.</span><span class="nf">unit</span><span class="p">.</span><span class="nf">location</span> <span class="sx">%&gt;
end
</span></code></pre></div></div>
<p>On the first call to the database, Smith’s program gathers all the soldiers, same as Smythe’s program. Advantage? No one. However, on the second call to the database, Smith’s program loads up all of the unit data. Now, as the view loops through each of the soldiers, a soldier’s name and location can be provided without any further database queries.</p>
<p>General Washington received the important data about his troop locations much sooner and the rest was history (9 brutal, war filled years of history).</p>
<p>So the next time someone tells you your app has an N + 1 problem, don’t shrug it off thinking it doesn’t matter. It might not just be the scalability of your app that’s on the line, it could very well be the fate of the entire freaking world. Don’t mess it up!</p>
<p><em>*Some of the history shared here may not be entirely accurate. George Washington probably didn’t invent a solution to the N+1 problem and Smith and Smythe probably weren’t building Rails apps. If you’re building a Rails app though, you should care about N+1. Learn more about Eager Loading by reading the <a href="http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Eager+loading+of+associations">ActiveRecord documentation</a>.</em></p>
</description>
<pubDate>Sun, 20 Jul 2014 12:26:51 -1000</pubDate>
<link>/n-plus-1/sql/activerecord/2014/07/20/a-tale-of-two-georges-refactoring-history.html</link>
<guid isPermaLink="true">/n-plus-1/sql/activerecord/2014/07/20/a-tale-of-two-georges-refactoring-history.html</guid>
<category>n-plus-1</category>
<category>sql</category>
<category>activerecord</category>
</item>
<item>
<title>Teaching a Computer Ancient Greek</title>
<description><p>TL;DR - It’s really hard to teach a computer Ancient Greek.</p>
<p>With the World Cup in full swing, I realize that’s where most people’s flag waving, nationalistic pride is focused. But there’s a different kind of nation vs nation drama about to unfold in Beijing, China. It’s the <a href="http://www.ioling.org">International Linguistics Olympiad</a> of course!</p>
<figure class="bt-video-container" style="padding-bottom:75.00%"><a class="youtube" href="http://www.youtube.com/watch?v=-Fu44oJqDjI" data-videoid="-Fu44oJqDjI" data-width="480" data-height="360">YouTube Video</a></figure>
<p>The International Linguistics Olympiad pits teams from around the world against each other to solve problems like the following:</p>
<p><img class="img-center" src="/images/posts/linguistics-question.png" width="468px" height="381px" alt="This is One of the Easy Problems! title:Ancient Greek to English IOL Problem" /></p>
<p>With an entire holiday weekend stretching out before us, my husband and I decided to see if we could write a program that could solve problems like the one above.</p>
<p>My initial plan was to use brute force to break the phrases into progressively smaller chunks and use a nested hash to keep track of how frequently those chunks appear in each language (the assumption being if they appear roughly the same number of times, they must map to each other).</p>
<p>Having a degree in Linguistics (and perhaps a greater desire to not spend the entire weekend coding) my husband suggested we focus on sanitizing the data a bit (e.g. removing endings to find overlap in root words) and look for matching <a href="http://en.wikipedia.org/wiki/N-gram">n-grams</a>. Frankly, an n-gram sounds like a fancy way of saying ‘break the phrase into progressively smaller chunks and compare them’ but it’s a $10 word, so I’m going with it.</p>
<p>Our first step was to write some helper methods to take input sentences and turn them into nested lists of sentences broken into words broken into ngrams.</p>
<p>Example: ( (‘I am happy.’ , ‘You are happy!’) ) =&gt; ( ((‘kno’, ‘now’, ‘know’)) , ((‘you’) , (‘kno’, ‘now’, ‘know’)) )</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">parse_words</span> <span class="p">(</span><span class="n">sentence_list</span><span class="p">):</span>
<span class="c"># create a new list to store lists of sentences, broken into words</span>
<span class="n">word_list</span> <span class="o">=</span> <span class="p">[]</span>
<span class="c"># chop up each sentence into a list of words using regex</span>
<span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">sentence_list</span><span class="p">:</span>
<span class="c"># create a temporary tuple of words and a permanent list where filtered words will be stored</span>
<span class="n">temp_words</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">split</span> <span class="p">(</span><span class="s">'</span><span class="err">\</span><span class="s">W+'</span><span class="p">,</span> <span class="n">s</span><span class="p">)</span>
<span class="n">words_in_s</span> <span class="o">=</span> <span class="p">[]</span>
<span class="c"># take the temporary list of words and add each, uncapsed, to the permanent list</span>
<span class="k">for</span> <span class="n">w</span> <span class="ow">in</span> <span class="n">temp_words</span><span class="p">:</span>
<span class="c"># only add the word to the new permanent list if it's not empty ''</span>
<span class="k">if</span> <span class="n">w</span> <span class="o">!=</span> <span class="s">''</span><span class="p">:</span>
<span class="n">words_in_s</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">w</span><span class="o">.</span><span class="n">lower</span><span class="p">())</span>
<span class="c"># add the permanent list to the total word_list (the list of all sentences, broken into words)</span>
<span class="n">word_list</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">words_in_s</span><span class="p">)</span>
<span class="k">return</span> <span class="n">word_list</span>
<span class="k">def</span> <span class="nf">parse_ngrams</span> <span class="p">(</span><span class="n">word_list</span><span class="p">,</span> <span class="n">gram_length</span><span class="o">=</span><span class="mi">3</span><span class="p">):</span>
<span class="c"># create a new list to store lists of sentences, broken into ngrams</span>
<span class="n">ngram_list</span> <span class="o">=</span> <span class="p">[]</span>
<span class="c"># chop up each sentence into a list of ngrams of all reasonable lengths using NLTK.util ngrams (imported at top of this py)</span>
<span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">word_list</span><span class="p">:</span>
<span class="c"># drill down into the sentences</span>
<span class="n">this_sentence</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">w</span> <span class="ow">in</span> <span class="n">s</span><span class="p">:</span>
<span class="c"># drill down to the words in the sentence</span>
<span class="n">this_word</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span> <span class="p">(</span><span class="n">gram_length</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">w</span><span class="p">)):</span>
<span class="c"># break the word down into all ngrams between user's gram_length and the word's length </span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">ngrams</span><span class="p">(</span><span class="n">w</span><span class="p">,</span><span class="n">i</span><span class="p">):</span>
<span class="c"># ngrams returns a tuple; make entries into strings</span>
<span class="n">this_gram</span> <span class="o">=</span> <span class="s">''</span>
<span class="k">for</span> <span class="n">char</span> <span class="ow">in</span> <span class="n">j</span><span class="p">:</span>
<span class="n">this_gram</span> <span class="o">+=</span> <span class="n">char</span>
<span class="c"># add each string into a list for each word</span>
<span class="n">this_word</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">this_gram</span><span class="p">)</span>
<span class="c"># if the word's not empty, add this word into a list for each sentence</span>
<span class="k">if</span> <span class="n">this_word</span> <span class="o">!=</span> <span class="p">[]:</span>
<span class="n">this_sentence</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">this_word</span><span class="p">)</span>
<span class="c"># add each sentence back into the total list</span>
<span class="n">ngram_list</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">this_sentence</span><span class="p">)</span>
<span class="k">return</span> <span class="n">ngram_list</span>
</code></pre></div></div>
<p>Next we wrote a function to deal with sanitizing and counting words in the English sentences. It would take a list of English sentences broken into words, then determine the frequency count and location of each word within the list. For anyone that cares, we’re using a fuzzy definition of word closer to “lexical item”.</p>
<p>Example:
english_sentences( ((‘I’, ‘am’, ‘not’, ‘happy’) , (‘You’, ‘are’, ‘very’, ‘very’, ‘happy’)) ) =&gt; [[‘happy’, [0, 1]], [‘very’, [1, 1]]]</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">english_sentences</span> <span class="p">(</span><span class="n">word_list</span><span class="p">):</span>
<span class="n">word_dict</span> <span class="o">=</span> <span class="p">{}</span> <span class="c"># will be used to associate occurrences of words with when and where they occur in text</span>
<span class="c"># use the word list to go thru the example sentences, look for occurrences &amp; put those occurrences in word_dict</span>
<span class="c"># grab each word from our list</span>
<span class="k">for</span> <span class="n">sentence</span> <span class="ow">in</span> <span class="n">word_list</span><span class="p">:</span>
<span class="k">for</span> <span class="n">word</span> <span class="ow">in</span> <span class="n">sentence</span><span class="p">:</span>
<span class="c"># NEW WORD FOUND: add dict entry for this frequency and index</span>
<span class="k">if</span> <span class="n">word</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">word_dict</span><span class="p">:</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">word</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="p">[</span><span class="n">word_list</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">sentence</span><span class="p">)]</span> <span class="p">]</span>
<span class="c"># ANOTHER INSTANCE FOUND: augment dict entry for this frequency and index</span>
<span class="k">elif</span> <span class="n">word</span> <span class="ow">in</span> <span class="n">word_dict</span><span class="p">:</span>
<span class="c"># increase the frequency count by 1</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">word</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="c"># list the index of the sentence in which the word occurs</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">word</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">word_list</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">sentence</span><span class="p">))</span>
<span class="c"># FUZZY MATCH TEST: add the stem of words that contain common suffixes</span>
<span class="c"># </span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">word</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">3</span><span class="p">:</span>
<span class="c"># filter for longer words to avoid overmatching</span>
<span class="c"># check if the last letter is a suffix</span>
<span class="k">if</span> <span class="n">word</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">word</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">:</span><span class="nb">len</span><span class="p">(</span><span class="n">word</span><span class="p">)]</span> <span class="ow">in</span> <span class="p">(</span><span class="s">'s'</span><span class="p">,</span> <span class="s">'d'</span><span class="p">):</span>
<span class="n">stem</span> <span class="o">=</span> <span class="n">word</span><span class="p">[:</span><span class="nb">len</span><span class="p">(</span><span class="n">word</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="c"># increase count and index if it's already in the dict</span>
<span class="k">if</span> <span class="n">stem</span> <span class="ow">in</span> <span class="n">word_dict</span><span class="p">:</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">stem</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">stem</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">append</span> <span class="p">(</span><span class="n">word_list</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">sentence</span><span class="p">))</span>
<span class="c"># add stem if it's not in dict</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">stem</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span> <span class="p">,</span> <span class="p">[</span><span class="n">word_list</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">sentence</span><span class="p">)]</span> <span class="p">]</span>
<span class="c"># check if the last two letters are a suffix</span>
<span class="k">if</span> <span class="n">word</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">word</span><span class="p">)</span><span class="o">-</span><span class="mi">2</span><span class="p">:</span><span class="nb">len</span><span class="p">(</span><span class="n">word</span><span class="p">)]</span> <span class="ow">in</span> <span class="p">(</span><span class="s">'es'</span><span class="p">,</span> <span class="s">'ed'</span><span class="p">,</span> <span class="s">'er'</span><span class="p">):</span>
<span class="n">stem</span> <span class="o">=</span> <span class="n">word</span><span class="p">[:</span><span class="nb">len</span><span class="p">(</span><span class="n">word</span><span class="p">)</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span>
<span class="c"># check to see if last 2 chars of stem are geminate; if so, cut the stem shorter </span>
<span class="k">if</span> <span class="n">stem</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">stem</span><span class="p">)</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="n">stem</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">stem</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
<span class="n">stem_short</span> <span class="o">=</span> <span class="n">stem</span><span class="p">[:</span><span class="nb">len</span><span class="p">(</span><span class="n">stem</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">if</span> <span class="n">stem_short</span> <span class="ow">in</span> <span class="n">word_dict</span><span class="p">:</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">stem_short</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">stem_short</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">append</span> <span class="p">(</span><span class="n">word_list</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">sentence</span><span class="p">))</span>
<span class="c"># add stem if it's not in dict</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">stem_short</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span> <span class="p">,</span> <span class="p">[</span><span class="n">word_list</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">sentence</span><span class="p">)]</span> <span class="p">]</span>
<span class="c"># increase count and index of the stem if it's already in the dict</span>
<span class="k">if</span> <span class="n">stem</span> <span class="ow">in</span> <span class="n">word_dict</span><span class="p">:</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">stem</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">stem</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">append</span> <span class="p">(</span><span class="n">word_list</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">sentence</span><span class="p">))</span>
<span class="c"># add stem if it's not in dict</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">stem</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span> <span class="p">,</span> <span class="p">[</span><span class="n">word_list</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">sentence</span><span class="p">)]</span> <span class="p">]</span>
<span class="c"># check if the last three letters are a suffix</span>
<span class="k">elif</span> <span class="n">word</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">word</span><span class="p">)</span><span class="o">-</span><span class="mi">3</span><span class="p">:</span><span class="nb">len</span><span class="p">(</span><span class="n">word</span><span class="p">)]</span> <span class="ow">in</span> <span class="p">(</span><span class="s">'ing'</span><span class="p">,</span> <span class="s">'ers'</span><span class="p">,</span> <span class="s">'est'</span><span class="p">):</span>
<span class="n">stem</span> <span class="o">=</span> <span class="n">word</span><span class="p">[:</span><span class="nb">len</span><span class="p">(</span><span class="n">word</span><span class="p">)</span><span class="o">-</span><span class="mi">3</span><span class="p">]</span>
<span class="c"># check to see if last 2 chars of stem are geminate; if so, cut the stem shorter </span>
<span class="k">if</span> <span class="n">stem</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">stem</span><span class="p">)</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="n">stem</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">stem</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
<span class="n">stem_short</span> <span class="o">=</span> <span class="n">stem</span><span class="p">[:</span><span class="nb">len</span><span class="p">(</span><span class="n">stem</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">if</span> <span class="n">stem_short</span> <span class="ow">in</span> <span class="n">word_dict</span><span class="p">:</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">stem_short</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">stem_short</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">append</span> <span class="p">(</span><span class="n">word_list</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">sentence</span><span class="p">))</span>
<span class="c"># add stem if it's not in dict</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">stem_short</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span> <span class="p">,</span> <span class="p">[</span><span class="n">word_list</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">sentence</span><span class="p">)]</span> <span class="p">]</span>
<span class="c"># increase count and index of the stem if it's already in the dict</span>
<span class="k">if</span> <span class="n">stem</span> <span class="ow">in</span> <span class="n">word_dict</span><span class="p">:</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">stem</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">stem</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">append</span> <span class="p">(</span><span class="n">word_list</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">sentence</span><span class="p">))</span>
<span class="c"># add stem if it's not in dict</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">stem</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span> <span class="p">,</span> <span class="p">[</span><span class="n">word_list</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">sentence</span><span class="p">)]</span> <span class="p">]</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">pass</span>
<span class="c"># create a list in which all found words and locations will be stored</span>
<span class="n">example_map</span> <span class="o">=</span> <span class="p">[]</span>
<span class="c"># add to list only words that occur more than once, along with their locations</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">word_dict</span><span class="p">:</span>
<span class="c"># get rid of common little words for easier comparison</span>
<span class="k">if</span> <span class="n">k</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">(</span><span class="s">'the'</span><span class="p">,</span> <span class="s">'a'</span><span class="p">,</span> <span class="s">'an'</span><span class="p">,</span> <span class="s">'if'</span><span class="p">,</span> <span class="s">'for'</span><span class="p">,</span> <span class="s">'of'</span><span class="p">,</span> <span class="s">'to'</span><span class="p">,</span> <span class="s">'at'</span><span class="p">):</span>
<span class="k">if</span> <span class="n">word_dict</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">example</span> <span class="o">=</span> <span class="p">[</span><span class="n">k</span> <span class="p">,</span> <span class="n">word_dict</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="p">]</span>
<span class="n">example_map</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">example</span><span class="p">)</span>
<span class="c"># return only the numbers in the example map, unweighted by frequency occurrence</span>
<span class="n">return_vals</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">example_map</span><span class="p">)</span> <span class="p">):</span>
<span class="c"># iterate through results, dig out only occurrence locations, put them in new list with no dups</span>
<span class="k">if</span> <span class="n">example_map</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">return_vals</span><span class="p">:</span>
<span class="n">return_vals</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">example_map</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">1</span><span class="p">])</span>
<span class="k">return</span> <span class="n">return_vals</span>
</code></pre></div></div>
<p>Next we needed to deal with the list of unknown sentences. We iterate through the sentence and determine if any of their grams show up more than once. Our output is a list of all the examples of multiple matches, including which sentences they occur in.</p>
<p>Example:
puzzle_sentences( ((‘zzxzzz gyyyggr’) , (‘zzz yyyyxyg’)) ) =&gt; [[‘zzz’, [0, 1]], [‘yyyy’, [0, 1]]]</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">puzzle_sentences</span> <span class="p">(</span><span class="n">word_list</span><span class="p">):</span>
<span class="n">word_dict</span> <span class="o">=</span> <span class="p">{}</span> <span class="c"># will be used to associate occurrences of words with when and where they occur in text</span>
<span class="c"># use the word list to go thru the example sentences, look for occurrences &amp; put those occurrences in word_dict</span>
<span class="c"># grab each word from our list</span>
<span class="k">for</span> <span class="n">sentence</span> <span class="ow">in</span> <span class="n">word_list</span><span class="p">:</span>
<span class="k">for</span> <span class="n">word</span> <span class="ow">in</span> <span class="n">sentence</span><span class="p">:</span>
<span class="k">for</span> <span class="n">gram</span> <span class="ow">in</span> <span class="n">word</span><span class="p">:</span>
<span class="c"># NEW MATCH FOUND: add dict entry for this frequency and index</span>
<span class="k">if</span> <span class="n">gram</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">word_dict</span><span class="p">:</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">gram</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="p">[</span><span class="n">word_list</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">sentence</span><span class="p">)]</span> <span class="p">]</span>
<span class="c"># ANOTHER INSTANCE FOUND: augment dict entry for this frequency and index</span>
<span class="k">elif</span> <span class="n">gram</span> <span class="ow">in</span> <span class="n">word_dict</span><span class="p">:</span>
<span class="c"># increase the frequency count by 1</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">gram</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="c"># list the index of the sentence in which the word occurs</span>
<span class="n">word_dict</span><span class="p">[</span><span class="n">gram</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">word_list</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">sentence</span><span class="p">))</span>
<span class="c"># create a list in which all matched ngrams will be stored</span>
<span class="n">example_map</span> <span class="o">=</span> <span class="p">[]</span>
<span class="c"># add to list only ngrams that occur more than once, along with locations</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">word_dict</span><span class="p">:</span>
<span class="k">if</span> <span class="n">word_dict</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">example</span> <span class="o">=</span> <span class="p">[</span><span class="n">k</span> <span class="p">,</span> <span class="n">word_dict</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="p">]</span>
<span class="n">example_map</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">example</span><span class="p">)</span>
<span class="c"># return only the numbers in the example map, unweighted by frequency occurrence</span>
<span class="n">return_vals</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">example_map</span><span class="p">)</span> <span class="p">):</span>
<span class="c"># iterate through results, dig out only occurrence locations, put them in new list with no dups</span>
<span class="k">if</span> <span class="n">example_map</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">return_vals</span><span class="p">:</span>
<span class="n">return_vals</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">example_map</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">1</span><span class="p">])</span>
<span class="k">return</span> <span class="n">return_vals</span>
</code></pre></div></div>
<p>Then we took the list of lists of occurence locations and searched it for degree-of-separation patterns.</p>
<p>e.g. traversing [[0,1,3],[0,2,4]], looking at the key 1:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 1 1
/ \ / \
0 3 Y Y
/ \ / \
2 4 N N
</code></pre></div></div>
<p>yields the entry 1: [[Y,Y],[N,N]]</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">deg_separ_matcher</span> <span class="p">(</span><span class="n">loc_list</span><span class="p">):</span>
<span class="n">pattern_dict</span> <span class="o">=</span> <span class="p">{}</span>
<span class="c"># create a basic dictionary associating each num with other nums that occur in same list at any point</span>
<span class="k">for</span> <span class="n">locations</span> <span class="ow">in</span> <span class="n">loc_list</span><span class="p">:</span>
<span class="c"># drill into list of nums</span>
<span class="k">for</span> <span class="n">loc</span> <span class="ow">in</span> <span class="n">locations</span><span class="p">:</span>
<span class="c"># drill down to nums themselves</span>
<span class="c"># create a list of locations that cooccur with loc</span>
<span class="k">if</span> <span class="n">loc</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">pattern_dict</span><span class="p">:</span>
<span class="c"># new dictionary entry if num isn't already a key</span>
<span class="n">pattern_dict</span><span class="p">[</span><span class="n">loc</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">loc2</span> <span class="ow">in</span> <span class="n">locations</span><span class="p">:</span>
<span class="c"># add nums that aren't already in that value and that aren't identical to the key (keys always occur with themselves in a list!)</span>
<span class="k">if</span> <span class="n">loc2</span> <span class="o">!=</span> <span class="n">loc</span> <span class="ow">and</span> <span class="n">loc2</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">pattern_dict</span><span class="p">[</span><span class="n">loc</span><span class="p">]:</span>
<span class="n">pattern_dict</span><span class="p">[</span><span class="n">loc</span><span class="p">]</span><span class="o">.</span><span class="n">append</span> <span class="p">(</span><span class="n">loc2</span><span class="p">)</span>
<span class="c"># take pattern dictionary above and branch patterns based on degree of separation of cooccurrences</span>
<span class="n">solutions_dict</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">loc</span> <span class="ow">in</span> <span class="n">pattern_dict</span><span class="p">:</span>
<span class="n">lvl_1</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">lvl_2</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">lvl_3</span> <span class="o">=</span> <span class="p">[]</span>
<span class="c"># dig into the first branch. All these cooccur with loc, so pass Y for each</span>
<span class="k">for</span> <span class="n">coloc</span> <span class="ow">in</span> <span class="n">pattern_dict</span><span class="p">[</span><span class="n">loc</span><span class="p">]:</span>
<span class="n">lvl_1</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">'Y'</span><span class="p">)</span>
<span class="n">lvl_1</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">coloc</span><span class="p">)</span>
<span class="c">#dig into the 2nd branch. Check if the number in question occurs within the coloc's list</span>
<span class="k">for</span> <span class="n">sub_coloc</span> <span class="ow">in</span> <span class="n">pattern_dict</span><span class="p">[</span><span class="n">coloc</span><span class="p">]:</span>
<span class="c"># is the original num in the list of nums that occur (sub_colocs) with the nums that occur (colocs) with the original num?</span>
<span class="k">if</span> <span class="n">loc</span> <span class="ow">in</span> <span class="n">pattern_dict</span><span class="p">[</span><span class="n">sub_coloc</span><span class="p">]</span> <span class="ow">and</span> <span class="n">sub_coloc</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">lvl_1</span><span class="p">:</span>
<span class="n">lvl_2</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">'Y'</span><span class="p">)</span>
<span class="n">lvl_2</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">sub_coloc</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">loc</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">pattern_dict</span><span class="p">[</span><span class="n">sub_coloc</span><span class="p">]</span> <span class="ow">and</span> <span class="n">sub_coloc</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">lvl_1</span><span class="p">:</span>
<span class="n">lvl_2</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">'N'</span><span class="p">)</span>
<span class="n">lvl_2</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">sub_coloc</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">pass</span>
<span class="c">#dig into the 3rd branch. Check if the number in question occurs within the sub_coloc's list</span>
<span class="k">for</span> <span class="n">sub_sub_coloc</span> <span class="ow">in</span> <span class="n">pattern_dict</span><span class="p">[</span><span class="n">sub_coloc</span><span class="p">]:</span>
<span class="c"># is the original num in the list of nums that occur (sub_sub_colocs) with the numbs that cooccur (sub_colocs) with the nums that cooccur (colocs) with the original num? </span>
<span class="k">if</span> <span class="n">loc</span> <span class="ow">in</span> <span class="n">pattern_dict</span><span class="p">[</span><span class="n">sub_sub_coloc</span><span class="p">]</span> <span class="ow">and</span> <span class="n">sub_sub_coloc</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">lvl_2</span><span class="p">:</span>
<span class="n">lvl_3</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">'Y'</span><span class="p">)</span>
<span class="n">lvl_3</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">'N'</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">loc</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">pattern_dict</span><span class="p">[</span><span class="n">sub_sub_coloc</span><span class="p">]</span> <span class="ow">and</span> <span class="n">sub_sub_coloc</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">lvl_2</span><span class="p">:</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">pass</span>
<span class="c"># add loc's first list to total list</span>
<span class="n">total</span> <span class="o">=</span> <span class="p">[</span><span class="n">lvl_1</span><span class="p">,</span> <span class="n">lvl_2</span><span class="p">,</span> <span class="n">lvl_3</span><span class="p">]</span>
<span class="n">solutions_dict</span><span class="p">[</span><span class="n">loc</span><span class="p">]</span> <span class="o">=</span> <span class="n">total</span>
<span class="k">return</span> <span class="n">solutions_dict</span>
</code></pre></div></div>
<p>Finally, we wrote a function that compared the 2 dictionaries to determine which keys have the same values, and pair those keys.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">def</span> <span class="nf">dict_compar</span> <span class="p">(</span><span class="n">d1</span><span class="p">,</span> <span class="n">d2</span><span class="p">):</span>
<span class="n">matches</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">k1</span><span class="p">,</span> <span class="n">v1</span> <span class="ow">in</span> <span class="n">d1</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span>
<span class="k">for</span> <span class="n">k2</span><span class="p">,</span> <span class="n">v2</span> <span class="ow">in</span> <span class="n">d2</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span>
<span class="k">if</span> <span class="n">v1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s">'Y'</span><span class="p">)</span> <span class="o">==</span> <span class="n">v2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s">'Y'</span><span class="p">)</span> <span class="ow">and</span> <span class="n">v1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s">'N'</span><span class="p">)</span> <span class="o">==</span> <span class="n">v2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s">'N'</span><span class="p">):</span>
<span class="k">if</span> <span class="n">v1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s">'Y'</span><span class="p">)</span> <span class="o">==</span> <span class="n">v2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s">'Y'</span><span class="p">)</span> <span class="ow">and</span> <span class="n">v1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s">'N'</span><span class="p">)</span> <span class="o">==</span> <span class="n">v2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s">'N'</span><span class="p">):</span>
<span class="k">if</span> <span class="n">v1</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s">'Y'</span><span class="p">)</span> <span class="o">==</span> <span class="n">v2</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s">'Y'</span><span class="p">)</span> <span class="ow">and</span> <span class="n">v1</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s">'N'</span><span class="p">)</span> <span class="o">==</span> <span class="n">v2</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s">'N'</span><span class="p">):</span>
<span class="n">matches</span><span class="o">.</span><span class="n">append</span> <span class="p">([</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">])</span>
<span class="k">return</span> <span class="n">matches</span>
</code></pre></div></div>
<p>In the end, we were able to get it to identify 2 out of 8 matches correctly. Not exactly a passing grade.</p>
<p>At this point I decided to take an entirely different approach and look for a Ruby gem that works with Google Translate. This gem totally exists, but, you have to get your own API key from Google and that’s not free.</p>
<p>There is no way I was shelling out my precious pizza money for that token when I can make the same queries via the web and scrape the data. I was gearing up to work on the scraper when it occurred to me that I should check to see if the data that I would get from Google Translate would work for my purposes.</p>
<p>That’s when I discovered Google Translate doesn’t have an Ancient Greek option. Apparently the folks at Google are too self absorbed to anticipate that I might one day need to do a random translation of Ancient Greek so it never got built into their free web app. The nerve!
So, for now, the participants in the International Linguistics Olympiad can breath easy. They won’t be replaced by a computer….yet!</p>
</description>
<pubDate>Tue, 08 Jul 2014 12:13:51 -1000</pubDate>
<link>/linguistics/python/ruby/2014/07/08/teaching-a-computer-ancient-greek.html</link>
<guid isPermaLink="true">/linguistics/python/ruby/2014/07/08/teaching-a-computer-ancient-greek.html</guid>
<category>linguistics</category>
<category>python</category>
<category>ruby</category>
</item>
<item>
<title>A Fun Way to Help Out</title>
<description><p>I’m a relatively new programmer and I frequently have questions about how things work. When a series of well-crafted Google searches can’t turn up the answer, I know exactly where to go. I reach out to my brother-in-law. He’s one of those guys that’s been programming since he was knee-high to a broomstick and now he’s CTO of a tech startup.</p>
<p>While I’m sure he has more interesting coding problems to solve than mine, he’s always got a few seconds to point me in the right direction. Literally - a few seconds - because that’s how long it takes him to diagnose issues I’ve been tracking down for hours.</p>
<p>Whether it’s a family member, close friend, former professor or someone else, these kinds of relationships are invaluable. Invaluable - if you’re lucky enough to have them. But what do learners in communities that don’t have a history of being computer programmers do? If you’re the first person in your circle that’s ever touched a piece of code, who do you ask when you’re stuck?</p>
<p>That’s one of the problems that schools like the Bronx Academy for Software Engineering (BASE) are trying solve by reaching out to community volunteers.</p>
<p><a href="http://bronxsoftware.org"><img class="img-center" src="/images/posts/base-logo.png" width="150px" height="150px" alt="BASE Logo" /></a></p>
<p>Last Saturday, I had the opportunity to work with a group of students from BASE that were coming to a weekend course put on by The Flatiron School. It was taught by Victoria Freedman - Flatiron’s Lead Instructor for their high school program. She walked them through basic commands on the command line, introduced them to version control with git and GitHub and had them code their own basic calculator program in Ruby.</p>
<p>While she was teaching, my job was to answer side questions and help keep everyone caught up. During the 5 hours I spent there, I:</p>
<ul>
<li>reinstalled a bash profile so it matched the standard one used in the examples</li>
<li>helped multiple kids figure out how to get set up with GitHub accounts</li>
<li>walked through the git code for cloning repos (multiple times - this one seems to be a tough one for beginners)</li>
<li>helped debug some Ruby code</li>
<li>ate a free sammich!</li>
<li>hung out with some amazing kids that are passionate about coding</li>
</ul>
<p>Not bad for someone that hadn’t touched the command line and certainly hadn’t used any git until about 3 weeks earlier. I had a blast and I was able to solidify some concepts in my own mind by explaining them to other people. I also laughed every time I heard myself echoing the instructors at Flatiron, “Lines of code are free. Just practice coding. GitHub repositories don’t cost anything. Practice making them until you understand it.” I may or may not have (figuratively) rolled my eyes when they said it to me two weeks earlier, but it had still worked its way into my brain and now I was passing that great advice along.</p>
<p>Which brings me to my point - if you’ve got one solid week of experience, you can be the person that helps out the guy that has questions on day one. If you’ve got a year (or more) under your belt, even better! There are plenty of people that could use mentoring in software development and many of them can only get that mentoring through volunteer programs.</p>
<p>If you would like to volunteer to help out at BASE, <a href="http://www.imentor.org/become-a-mentor">go here</a> and complete the application (being sure to mention BASE in the application). If you’re not Bronx-adjacent, don’t worry, there will be plenty of opportunities to volunteer in your area - just spend a bit of time searching and you’ll find a program that will be a good fit for you.</p>
</description>
<pubDate>Sun, 29 Jun 2014 12:11:21 -1000</pubDate>
<link>/base/teaching/2014/06/29/a-fun-way-to-help-out.html</link>
<guid isPermaLink="true">/base/teaching/2014/06/29/a-fun-way-to-help-out.html</guid>
<category>base</category>
<category>teaching</category>
</item>
<item>
<title>Ruby and the Amazing Splat *</title>
<description><p>On occasion, while perusing other people’s code and marveling at the many ways there are to solve even simple problems, I’ve come across a mysterious asterisk that appears to have magical properties.</p>
<p>It most commonly shows up attached to an argument in a method signature like this:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">things_liked</span><span class="p">(</span><span class="nb">name</span><span class="p">,</span> <span class="o">*</span><span class="n">items</span><span class="p">)</span>
<span class="n">items</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">item</span><span class="o">|</span>
<span class="nb">puts</span> <span class="s2">"</span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="s2"> likes </span><span class="si">#{</span><span class="n">item</span><span class="si">}</span><span class="s2">."</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>
<p>That method structure was very familiar, but I was never entirely sure about the asterisk’s purpose. I grabbed a couple variables, tossed them in, and was surprised to see that the method behaved exactly how it would have behaved if the asterisk wasn’t there.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">things_liked</span><span class="p">(</span><span class="s2">"Jessica"</span><span class="p">,</span> <span class="s2">"hyenas"</span><span class="p">)</span>
<span class="c1">#=&gt; Jessica likes hyenas.</span>
</code></pre></div></div>
<p>It seemed unlikely that the little guy just hangs out and does nothing, so I dug further and discovered that it’s called the “splat operator” and it does some amazing things.</p>
<p>Splat can be used in methods when you aren’t sure how many variables will be passed in. Perhaps Jessica likes many things but hyenas are more simple in their passions. If you use the power of splat, you can handle these variations in a single method.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>jess = ["hyenas", "ruby", "long runs"]
hyena = ["crunchy bones"]
things_liked("Jessica", jess)
#=&gt; Jessica likes hyenas.
#=&gt; Jessica likes ruby.
#=&gt; Jessica likes long runs.
things_liked("Hyena", hyena)
#=&gt; Hyena likes crunchy bones.
</code></pre></div></div>
<p>That alone should be enough to earn splat its place in your future code…but splat is no lightweight and there’s so much more it can do!</p>
<p>I found a great gist from <a href="https://github.com/rubyspec/rubyspec/blob/master/language/splat_spec.rb">RubySpec</a> that covers the many wonderful (and occassionally odd) behaviors of splat.</p>
<p>Here are a few that I found particularly noteworthy.</p>
<p>Splat automatically puts the values it is called on in an array…</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">x</span> <span class="o">=</span> <span class="mi">1</span>
<span class="c1">#=&gt; 1</span>
<span class="n">x</span> <span class="o">=</span> <span class="o">*</span><span class="mi">1</span>
<span class="c1">#=&gt; [1]</span>
</code></pre></div></div>
<p>…unless you splat nil. Splat nil and you get an empty array.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">x</span> <span class="o">=</span> <span class="o">*</span><span class="kp">nil</span>
<span class="c1">#=&gt; []</span>
</code></pre></div></div>
<p>It can be used to create hashes from arrays. All of the items with even indexes become keys while the odds become values.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">array</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="s2">"David"</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="s2">"Lillith"</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="s2">"Jessica"</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="s2">"Lucas"</span><span class="p">]</span>
<span class="no">Hash</span><span class="p">[</span><span class="o">*</span><span class="n">array</span><span class="p">]</span>
<span class="c1">#=&gt; {1 =&gt; "David", 2 =&gt; "Lillith", 3 =&gt; "Jessica", 4 =&gt; "Lucas"}</span>
</code></pre></div></div>
<p>Splat can also come in handy when you want to gather up all but the first, last or first and last items in an array.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">first</span><span class="p">,</span> <span class="o">*</span><span class="n">rest</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span>
<span class="c1">#=&gt; first = 1, rest = [2,3,4]</span>
<span class="o">*</span><span class="n">rest</span><span class="p">,</span> <span class="n">last</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span>
<span class="c1">#=&gt; rest = [1,2,3], last = 4</span>
<span class="n">first</span><span class="p">,</span> <span class="o">*</span><span class="n">center</span><span class="p">,</span> <span class="n">last</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span>
<span class="c1">#=&gt; first = 1, center = [2,3], last = 4</span>
</code></pre></div></div>
<p>With visions of splat operators running through my head, I decided to experiment and see if it could be used to grab the first character in a string (which happened to be necessary for an assignment I was working on). With a little bit of trial and error, I came up with the following:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">x</span><span class="p">,</span> <span class="o">*</span><span class="n">y</span> <span class="o">=</span> <span class="s2">"hello"</span><span class="p">.</span><span class="nf">split</span><span class="p">(</span><span class="s2">""</span><span class="p">)</span>
<span class="n">x</span> <span class="o">=&gt;</span> <span class="s2">"h"</span>
<span class="n">y</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="s2">"e"</span><span class="p">,</span> <span class="s2">"l"</span><span class="p">,</span> <span class="s2">"l"</span><span class="p">,</span> <span class="s2">"o"</span><span class="p">]</span>
</code></pre></div></div>
<p>WHICH TOTALLY WORKS!!!!</p>
<p>But, if we’re going to be responsible coders, we need to remember that just because we can do something doesn’t mean we should. Unless we want our code to confuse people (including ourselves when we come back to it in a few months and wonder what the heck we were doing), we should use the right tools for the job.</p>
<p>So we’ll have to say no to peppering our code with splat just for the pure joy we get from yelling splat every time we type it but we’ll never again have to be afraid to use it appropriately in our code.</p>
</description>
<pubDate>Tue, 24 Jun 2014 13:00:25 -1000</pubDate>
<link>/code/ruby/2014/06/24/ruby-and-the-amazing-splat.html</link>
<guid isPermaLink="true">/code/ruby/2014/06/24/ruby-and-the-amazing-splat.html</guid>
<category>code</category>
<category>ruby</category>
</item>
<item>
<title>Contributing to Open Source</title>
<description><p>In class the other day, we identified a likely error in the Ruby Docs documentation.</p>
<p>A quick side note, as someone who is involved in content creation at <a href="http://www.youtube.com/nativlang">NativLang</a>, my thoughts on what constitutes an error have evolved quite a bit.</p>
<p>An error is not:</p>
<ul>
<li>A music choice you dislike</li>
<li>An example you like or think is helpful being left out</li>
<li>Your pet region, language, food, etc not being included</li>
<li>Etc</li>
</ul>
<p>In general (serious about the generalization here - no guff from you philosophy majors out there), errors seem to come in two flavors:</p>
<ol>
<li>A factual claim that is made which is incorrect</li>
<li>A situation where the creator seemed to intend one thing but presented another (e.g. typos, uses the wrong word, a broken link, etc)</li>
</ol>
<p>The truth is, I’m so new to Ruby that I would not trust myself to identify an error; however, in this instance, the much more knowledgable instructor said it was likely an error.</p>
<p><img class="img-center" src="/images/posts/find-documentation.png" /></p>
<p>That got me thinking, how do errors in open source get corrected?</p>
<p>In the grand old days of publishing, if you cared enough, you might send a letter to the publisher letting them know you found an error. Years later, if they cared enough, they’d correct it in a subsequent edition.</p>
<p>This is the brave new world of open source though, so it seems likely that there’s a much more immediate way of making changes. I went to the Ruby Docs home page and looked around. I found this in the footer - how convenient!</p>
<p><img class="img-center" src="/images/posts/documenting-the-ruby-language.png" /></p>
<p>As you might expect from a community as happy and helpful as the Ruby community, the Documentation page was full of step-by-step processes and how-tos (involving forking a repository - the newest of my skillz!).</p>
<p><img class="img-center" src="/images/posts/github-forking.gif" /></p>
<p>The process seems fairly simple:</p>
<ol>
<li>Fork the <a href="https://github.com/documenting-ruby/ruby">documentation repository</a></li>
<li>Open an <a href="https://github.com/documenting-ruby/ruby/issues/new">issue</a> (to let others know what you’re working on so there’s no duplication)</li>
<li>Submit a pull request so people know your work is ready to be reviewed</li>
<li>Prepare your patch for submission</li>
</ol>
<p>When I find some time this week (haha…no, really!) I plan to work on an update for that section of documentation (assuming someone else isn’t already working on it). It’ll be fun to contribute to an open source project - I’ll be a real Rubyist! - and it’s always nice to give back to a community that provides everything for free.</p>
<p>I’ll let you know how it goes!</p>
</description>
<pubDate>Tue, 10 Jun 2014 07:45:38 -1000</pubDate>
<link>/open-source/2014/06/10/contributing-to-open-source.html</link>
<guid isPermaLink="true">/open-source/2014/06/10/contributing-to-open-source.html</guid>
<category>open-source</category>
</item>
</channel>
</rss>