Skip to main content
Ben Nadel
It's not enough; but, not enough is better than nothing.
Ben Nadel at dev.Objective() 2015 (Bloomington, MN) with: Ryan Anklam
Ben Nadel at dev.Objective() 2015 (Bloomington, MN) with: Ryan Anklam@bittersweetryan )

Seven Languages In Seven Weeks By Bruce Tate - What An Adventure

By Ben Nadel on

About two months ago, I started reading Seven Languages in Seven Weeks by Bruce Tate. I went into the book with a significant understanding of only two programming Languages: ColdFusion and Javascript. Now, not only do I have a sense of how many programming languages there are out there (Tate's list of 7 was selected from over a hundred languages), I see that there are some radically different approaches to problem solving.

Ben Nadel After Reading Seven Languages In Seven Weeks! 

This book was straight up challenging! Tate does a good job of laying down a lot of the foundational concepts of each language; but, he really puts you through your paces. Most of the time, he merely points you in the right direction and then leaves it up to you to do the online research and connect the dots. Sometimes, I found this exhilarating; other times, I found this both frustrating and exhausting.

One of my favorite moments in the book, however, has nothing to do with any of the languages specifically; rather, it was a moment of clarity about the role of a language within a broader solution. When I started reading the book, I definitely thought of languages as being interchangeable. As such, I was always asking myself the question:

Yeah, this language is cool, but how do I get it to do all the amazingly powerful things that ColdFusion can do?

When you view languages as hot-swappable, I think this question is natural - it boils down to trade-offs. But, what I finally realized, going through this book, is that languages are not swappable; nor, should they be. Languages are designed to handle specific types of problems. The hard part is then having the wisdom to know when to apply a particular language to a particular type of problem.

Coming from a ColdFusion background, I am a bit of a generalist. As such, I tend to view a solution as relying on one language. But after talking with people like Sean Corfield, I am definitely starting to see that the "best" solution may contain 2 or 3 different programming languages all working in parallel.

That's a brave new world for me. This book has really opened my eyes to some new ways of thinking and some powerful forms of data manipulation. As you can see from my photo above, I'm tired; but, the journey was totally worth it.

Let's Give Some Stuff Away!

In honor of my Seven Languages journey, the good people at The Pragmatic Programmers have given me a discount code to give away. If you use the code at the Pragmatic Bookshelf:


... you'll get a 30% discount on either the print or electronic version of the Seven Languages in Seven Weeks book; but act fast, this coupon expires in a couple of days on February 2!

Let's Give Some MORE Stuff Away!

I think this book is awesome. As such, I'd like to give away a few copies of it myself. But, I want to foster an atmosphere of language appreciation. So here's how you enter: below, I am supplying the pseudo code for a problem. If you want to enter to win one of the free books, you have to translate the following pseudo code into the language of your choice within the comments of this post.

  1. Create a collection of names.
  2. Create a function that accepts a collection of names and an adjective and returns a new collection.
  3. The new collection must contain values in the form of, "NAME is so ADJECTIVE."
  4. Invoke this function.

NOTE: When posting code with the <code> tag, you can use Tabs or Spaces. However, if you use spaces, you must use 4-spaces to represent at tab.

You have until next Friday to post your code sample in the comments. And, remember to tell us all what language it is you are using!

The Journey In Its Totality

If you are curious about my Seven Languages in Seven Weeks journey, here are the related blog posts:

Have a great weekend!

Reader Comments


  • (function () {
  • var names = "john jacob jingleheimer schmidt".split(' '),
  • phrase = [],
  • nameCollector = function (n, adj) {
  • for (var i = 0, l = names.length; i < l; i++) {
  • phrase.push(names[i].toUpperCase() + " is so " + adj);
  • }
  • return phrase;
  • } (names, "amazing".toUpperCase());
  • console.log(nameCollector);
  • })();


Awesome stuff! Nice use of immediately-executed functions, especially in the context of return values.

To everyone:

Just a note to others - You don't have to make the Name/Adjective uppercase. Sorry about that - I put them in uppercase in my post to demonstrate substitution / interpolation.


  • names = ["alice", "bob", "charlie"]
  • def nameAdj(nameList, adj):
  • return ["%s is so %s" % (name, adj) for name in nameList]
  • newNames = nameAdj(names, "weird")
  • print newNames

ColdFusion (CFML):

  • <cfset names = listToArray("Napoleon,Kip,Tina,Pedro,Deb") />
  • <cffunction name="makePhrase" access="public" returntype="array" output="true" hint="">
  • <cfargument name="names" type="array" required="true" hint="list" />
  • <cfargument name="adj" type="string" required="true" />
  • <cfset local.phrases = ArrayNew(1) />
  • <cfloop from="1" to="#ArrayLen(arguments.names)#" index="nameIdx">
  • <cfset arrayAppend(local.phrases, "#UCase(arguments.names[nameIdx])# is so #arguments.adj#") />
  • </cfloop>
  • <cfreturn local.phrases />
  • </cffunction>
  • <cfset phrases = makePhrase(names,"FUNNY") />
  • <cfdump var="#phrases#" />


  • /// <summary>
  • /// A CSharp console program's main method.
  • /// </summary>
  • void Main()
  • {
  • var originalCollection = new List<string>() { "Will", "Sandler", "Martin" };
  • var modifiedCollection = GetNamesWithAdjectives(originalCollection, "funny");
  • foreach (string oneStatment in modifiedCollection)
  • {
  • Console.WriteLine(oneStatment);
  • }
  • }
  • /// <summary>
  • /// Function that gets a modified collection
  • /// </summary>
  • private static IEnumerable<string> GetNamesWithAdjectives(IEnumerable<string> collection, string adjective)
  • {
  • return collection.Select(name => name + " is so " + adjective);
  • }

  • (defparameter *names* (list "Josh" "Ben" "Ray"))
  • (defun addAdjective (namesList adjective)
  • (loop for i in namesList
  • append (list (concatenate 'string i " is so " adjective)) into newList
  • finally
  • (return (values newList))))
  • (addAdjective *names* "smart")

Who doesn't like Lisp?

I'm a sucker for PowerShell, the object based piping makes operating on collections a cinch:

  • Function NameIsSoAdjective($names, $adjective)
  • {
  • $names | foreach { "$_ is so $adjective" }
  • }
  • NameIsSoAdjective "Me","Myself","I" "awesome

I don't know about you guys, but I think it awesome how different each of these languages makes this approaches. So cool!


  • <?php
  • $names = array('Claire','Juliet','Kate','Penny','Charlotte','Sun','Shannon');
  • function nameAdjective($n, $v) {
  • foreach($n as $value){
  • $value .= " is so $v";
  • $values[] = $value;
  • }
  • return $values;
  • }
  • $newNames = nameAdjective($names, 'hot');
  • foreach($newNames as $new){
  • echo $new;
  • echo "<br />";
  • }
  • ?>

I thought I'd try a language I'd never heard of to see how difficult it would be. I may actually pick this up now based on how easy it was. (I'm just rehasing my Lisp prog here)

The language is REBOL

  • names: ["Josh" "Ben" "Ray"]
  • newList: []
  • addAdjective: func [namesList adjective] [
  • foreach item namesList [append newList rejoin[item " is so " adjective "."]]
  • ]
  • namesFinal: addAdjective names "smart"
  • print namesFinal


  • - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
  • NSArray *names = [NSArray arrayWithObjects:@"Homer",@"Marge",@"Bart",@"Lisa",@"Maggie",nil];
  • NSMutableArray *descriptions = [self describeNames:names asAdjective:@"freakin' awesome"];
  • NSLog(@"%@",descriptions);
  • }
  • - (NSMutableArray *)describeNames:(NSArray *)names asAdjective:(NSString *)adjective {
  • NSMutableArray *descriptions = [NSMutableArray array];
  • for(int i=0; i<[names count]; i++) {
  • [descriptions addObject:[NSString stringWithFormat:@"%@ is %@!",[names objectAtIndex:i],adjective]];
  • }
  • return descriptions;
  • }

  • soAdj :: String -> [String] -> [String]
  • soAdj adj names = [n ++ sentence | n <- names]
  • where sentence = " is so " ++ adj ++ "."
  • > let names = ["Ben", "Wilkins", "Mike", "Seth"]
  • > soAdj "serious" names
  • ["Ben is so serious.","Wilkins is so serious.","Mike is so serious.","Seth is so serious."]
  • > take 100000 . soAdj "infinite" . repeat $ "This list"
  • ["This list is so infinite.","This list is so infinite.", ...snip...

Nobody here handled an infinite list of names... Fortunately, there is Haskell.


Yeah :) Like you, I also started learning Haskell this week and I really like the idea of defining what something is rather than saying how something should be computed. It feels really mathematical, which, for me, is a big plus.

From all the languages displayed here, I'm partial to Python and Haskell. They are both very concise and pleasant. But I have to admit that I'm a bit biased..


ColdFusion is my love; but, even I can see how concise some of these other languages are. Like I said, one of the things I really came away with after reading this book was how powerful list manipulation is.

So many ways to write this;

  • /*
  • Create a collection of names.
  • Create a function that accepts a collection of names and an adjective and returns a new collection.
  • The new collection must contain values in the form of, "NAME is so ADJECTIVE."
  • Invoke this function.
  • */
  • var challenge = function(){
  • var _isSo = ' is so ',
  • /* predefine collections */
  • _collections = { sentences: [], names: [
  • { name: 'Jon' },
  • { name: 'Franz' },
  • { name: 'Pernille' },
  • { name: 'Sonja' },
  • { name: 'Laura' },
  • { name: 'Lois' }
  • ], adjectives: [
  • { adj: 'super' },
  • { adj: 'hot' },
  • { adj: 'new' },
  • { adj: 'available' },
  • { adj: 'latest' },
  • { adj: 'great' }
  • ]};
  • /**
  • * Returns a random number
  • */
  • function getRandom(max){
  • return Math.floor(Math.random() * max || 1);
  • }
  • /**
  • * Mix the names and adjectives collections
  • */
  • function mix(names, adjectives){
  • for (var name in names){
  • _collections.sentences.push(
  • names[name].name + _isSo + _collections.adjectives[
  • getRandom(_collections.adjectives.length)
  • ].adj
  • );
  • }
  • }
  • return {
  • getSentences: function(){
  • return mix(_collections.names, _collections.adjectives), _collections.sentences.toString();
  • }
  • }
  • }();
  • challenge.getSentences();

Here's mine in Ruby:

  • def map_adjective(names,adj)
  •{|name| "#{name} is so #{adj}"}
  • end
  • names = %w(adam jon andy dave fred wilson)
  • puts map_adjective(names,"funny"

Visual Basic .NET, with and without LINQ. (The C# example that already exists is similar enough it felt like cheating, so I implemented the version that doesn't use LINQ.) Both are idiomatic, though the non-LINQ implementation would be from before 2008 (or the product of a developer with high resistance to new features.)

Module Module1

Sub Main()
Dim names() As String = {"Bob", "Alice"}
Dim adjective As String = "stinky"

Dim linqSentences() As String = CreateSentencesWithLinq(names, adjective)
For Each sentence As String In linqSentences

Dim nonLinqSentences() As String = CreateSentencesWithoutLinq(names, adjective)
For Each sentence As String In nonLinqSentences
End Sub

Function CreateSentencesWithLinq(ByVal names As IEnumerable(Of String), ByVal adjective As String) As String()
Return names.Select(Function(name As String) String.Format("{0} is so {1}", name, adjective)).ToArray()
End Function

Function CreateSentencesWithoutLinq(ByVal names As IEnumerable(Of String), ByVal adjective As String) As String()
Dim sentences As New List(Of String)()
For Each name As String In names
sentences.Add(String.Format("{0} is so {1}", name, adjective))

Return sentences.ToArray()
End Function

End Module


Before I started programming in Pyhon I did a lot of PHP and I had no idea about the power of this stuff.

Python's list comprehensions just make me smile :D

  • >>> [(x, chr(x + 97)) for x in range(6) if not x % 2]
  • [(0, 'a'), (2, 'c'), (4, 'e')]

What makes ColdFusion special for you? I have to admit that, to me, it looks a bit like programming in what looks like a markup language. No offense.

A little pl/sql into the mix (one of the many, many ways to do this, I'm sure...especially depending on the collection type).

Tested in Oracle 10g by the way.

  • declare
  • CURSOR nameIsSo (nameList VARCHAR2, verb VARCHAR2) IS
  • SELECT REGEXP_SUBSTR( nameList, '[^,]+', 1, rownum) || ' is so ' || verb || '.' sentence
  • FROM dual
  • CONNECT BY LEVEL <= length (regexp_replace ( nameList, '[^,]+')) + 1;
  • begin
  • FOR rec IN nameIsSo( 'Ashley,Bre,Steph,Emily', 'radical')
  • LOOP
  • dbms_output.put_line(rec.sentence);
  • end;

I fail so hard for not only mixing up the HTML code tag with the one I'm used to using for forums, I also hit Enter too soon and submitted the intended explanation too early. I think I have to go run some laps or something as punishment. :(

No Ruby entries, yet?

  • names = ["John", "Paul", "George", "Ringo"]
  • def names_are_so_adjective(names, adjective)
  •{ |name| "#{name} is so #{adjective}" }
  • end
  • puts names_are_so_adjective(names, "rad")


List comprehensions are just awesomeness incarnate :) When I learned about those in this book, I was like, Whoa! Badass.

As far as ColdFusion, I just love how much stuff you can do. Clearly, all of these languages are very powerful and so is ColdFusion. What it lacks in syntax it makes up for with the enormity of the native library.


No worries my man - we can still see what's going on. I've heard of LINQ before, but never actually need any of the code that uses it.

@Marty, @Adam,

Ruby is pretty cool. When I started looking at that language, I was really thrown off by some of the syntax; but, by the end of the book, I was so warn down by minimal syntax that I might actually be coming around to loving it :)


Very interesting - I've never done anything like that at the SQL level. Is that an enterprise kind of thing? Or is that a wide supported concept (if you have any idea).


I like the way you mix the two lists together.


I spent a few days trying to learn how to program on the iPhone with Object-C and it just rubbed me the wrong way. What really irked me was the way you had to do so much manually allocation and de-allocation. Seemed like an archaic concept.


I'm not sure I've even heard of REBOL. It looks like another one of those ultra-concise languages.


I've heard a lot of people really praise Python. The one thing I was always iffy about was the requirement of white-space. I mean, don't get me wrong, I LOVE white-space; but, when it becomes a requirement, I was afraid that it would mess with my approach.


This is an interesting syntax:

$values[] = $value;

Is that like a self-push operator?


ColdFusion .. woot!


That's interesting - I know almost nothing about C#; I didn't realize it supported a sort-of inline function declaration for working with collections.


The whitespace in Python trips a lot of people up, and rubs others in a really bad way. However, one thing it's turned me to do is really evaluate my coding style and realize that if I end up with a ton of nested looping / control structures, there's probably a more elegant solution. In Python, because of the whitespace being important, your code ends up looking really ugly with a lot of nested loops/if-elses, so it kind of encourages you to do things in a more modular and articulate way.

Just my two cents, and I'm totally not saying other languages aren't elegant. For me personally, it's a bit easier to do in Python.

Just thought perl was missing. Although I am not sure the code qualifies?

  • @d = map sprintf("%s is so %s",$_,"perlish"), ("Morten","Ben","The lot");


That's actually a really good point. A while back, Brian Kotek presented the idea of Object Oriented Calisthenics:

One of the challenges was to not allow any function to nest more than twice. The idea being that, as you said, if you nest too much, there's probably a better way of doing it.


It's definitely groovy... but language is it (ha ha, sorry couldn't resist).


Ha ha, that might the record for the shortest entry.


From what I can gather it was originally intended for network communications and distributed computing. I figured in the spirit of things I'd try a language I had never tried before. I even found an online compiler. Syntax is pretty straight forward and it does some decent list evaluation. Although for list evals you can't go wrong with Lisp. But I'm a ColdFusion die hard all the way.


This time around, I was better with Lisp (Clojure) than I have been in the past; but as far as the book goes, I think I remember enjoying Io more than Lisp... though, in reality, my brain is just mush at this point.

Thank you for the discount code Ben! I just picked up my copy. I've enjoyed following your progress with it and I'm ready to dive in now.
Thanks again to you and folks at The Pragmatic Programmers!

Thought I should give it a more serious try and then I remembered playing around with moscow ml some ~10 years ago...

  • val list = ["Morten","Ben","The lot"] : string list;
  • fun map (f, adj, nil) = nil | map (f, adj, h::t) = (f(h, adj)) :: map (f, adj, t);
  • fun func (h,adj) = h ^ " is so " ^ adj;
  • map(func,"MLed",list);

This example does by no means take advantage of the tasty bits of ML, but even if my life depended on it I wouldn't be able to remember much of it.

I think I have to dive back into this old one

@Ben, of all the languages in that book (and in your brain), do you have a particular favorite? It's a big question, I know, all languages have their place.
That being said, what syntax to you find particularly beautiful and why?


Outstanding! I hope you enjoy it!


I'm certain I've never heard of MoscowML, let alone SML. It's bananas how many languages there are out there. The syntax for this one looks like Haskell a bit.


Let me think about this one for a bit - my brain needs a night of Netflix :)

Ruby code, more defensive version:

  • #!/usr/bin/env ruby
  • # Author: Greg Mefford
  • # * Create a collection of names.
  • names = %w{Ruby Ursula Bob Yuri}
  • # * Create a function that accepts a collection of names and an adjective
  • # and returns a new collection.
  • # * The new collection must contain values in the form of,
  • # "NAME is so ADJECTIVE."
  • def xs_are_so_y(names=["Everyone"], adjective="Lame")
  • unless names.is_a? Enumerable and{|n| n.respond_to? :upcase}.uniq == [true]
  • fail "You have to specify a collection of name Strings"
  • end
  • unless adjective.respond_to? :upcase
  • fail "You have to specify an adjective String"
  • end
  •{ |name| "#{name.upcase} is so #{adjective.upcase}"}
  • end
  • # * Invoke this function.
  • puts xs_are_so_y
  • puts xs_are_so_y(names, "Awesome")

This is in the J programming language. It includes definitions, invocation, and output.

  • names=: ;:'Miles Ella Jaco Wynton'
  • say_is_so=: [:,@> ([,' is so ',])&.>
  • names say_is_so <'cool.'
  • Miles is so cool.
  • Ella is so cool.
  • Jaco is so cool.
  • Wynton is so cool.

For more about J, see


$values[] = $value; creates an array called $values and adds each new value to the end of the array as the function loops through.

Thanks for doing this little contest too. I have enjoyed looking through everyone's code to see what they did with their languages. If I don't win one of the books I will definitely be buying this one!

@Ben, yeah, as a longtime CF/Java guy, the allocate/retain/release stuff in Objective-C drives me nuts. But it's worth it to see one's apps in the app store. :)

Check out the Head First iPhone Development book if you feel like giving it another shot. It's a fun read and cuts through all the complexity.

Like you Ben, I'm a CF and JS guy. Just picked up the 7 languages book today, but I have coworkers who could learn as well if I win a copy. :-) I use bash all the time to cat JS and CSS files prior to minification. Hadn't seen a regular ole bash script posted yet, so here's mine.

beatles=(John Paul George Ringo)
function rock(){
for i in ${beatles[@]}; do
rockers+=(${i}" is so "${2})
echo ${rockers[*]}
rock beatles Rockin!

Thx again for the contest and book discount!

Sorry about the bad markup, I'll try again!

Like you Ben, I'm a CF and JS guy. Just picked up the 7 languages book today, but I have coworkers who could learn as well if I win a copy. :-) I use bash all the time to cat JS and CSS files prior to minification. Hadn't seen a regular ole bash script posted yet, so here's mine.


  • #!/bin/bash
  • beatles=(John Paul George Ringo)
  • function rock(){
  • rockers=()
  • for i in ${beatles[@]}; do
  • rockers+=(${i}" is so "${2})
  • done
  • echo ${rockers[*]}
  • }
  • rock beatles Rockin!

Thx again for the contest and book discount!


ML is a fun(ctional) language to play around with and there are quite a few implementations of it.

I haven't played around with Haskell at all, but to my understanding Haskell is a pure functional language where as ML has some blurry edges when it come to that.

ML also shares similarities with javascript :)

  • (fn 0=>1 | n:int => n*(n-1))(10);

What I like about SML is that is has no loop sytax like for, each and while. All recursion is done through tail recursion which forces me to think of programmatic solutions differently than I would in other languages.

That said I never code in ML, its too frustrating and reminds me of hours of tedious homework :)

Here's a java submission. The language is very concerned with types and requires a bit of set up to execute a program with a function.

  • import java.util.Iterator;
  • import java.util.ArrayList;
  • public class Describer {
  • public static void main(String [] args) {
  • ArrayList<String> list = new ArrayList<String>();
  • list.add("Atticus Finch");
  • list.add("Holden Caulfield");
  • list.add("John Proctor");
  • String adjective = "fictitious";
  • Iterable<String> newList = describeIsSo(list, adjective);
  • for (String s: newList) {
  • System.out.println(s);
  • }
  • }
  • public static Iterable<String> describeIsSo(Iterable<String> collection, String adjective) {
  • ArrayList<String> newCollection = new ArrayList<String>();
  • for(String s : collection) {
  • newCollection.add(String.format("%s is so %s", s, adjective));
  • }
  • return newCollection;
  • }
  • }

I am disappointed that none of the Ruby solutions posted so far used the splat:

  • def describe(adjective, *names)
  • names.collect{|name| "#{name} is so #{adjective}"}
  • end
  • describe('awesome', 'Harry', 'Bob', 'John')

Here's a bit of Gosu...

  • var testNames = {"Bob", "Carol", "Ted", "Alice"}
  • function describe(names : List<String>, adjective : String) : List<String> {
  • return \name -> (name + " is so " + adjective))
  • }
  • describe(testNames, "awesome").each(\s -> print(s))

...that produces as output...

  • Bob is so awesome
  • Carol is so awesome
  • Ted is so awesome
  • Alice is so awesome


  • awk -v adjective="simples" '{$2=adjective; print $1" is "$2}' ./nameList.txt >> nameWithAdjective.txt

yeah ok there is no function or collection unless I guess you allow a text file as a collection.

Wow, I am really loving these examples! What's cool is that not only are the languages different; but, so many of the approaches bring a slightly different twist to the solution. Very very cool stuff!

Since the CF Version has already been posted, here is the CFScript version:

  • <cfscript>
  • names = "Marky,Ricky,Danny,Terry,Mikey,Davey,Timmy,Tommy,Joey,Robby,Johnny,Brian";
  • function add_adjective ( names, adjective ) {
  • return listChangeDelims( names, " is so " & adjective & "," ) & iif(listLen(names), DE(" is so " & adjective), DE(""));
  • }
  • writeOutput( add_adjective( names, "funny" ) );
  • </cfscript>


  • sequence names
  • names = {"Matthew","Mark","Luke","John"}
  • function Insert_IsSo(name, adj)
  • return name & "is so" & adj
  • end function
  • for i = 1 to length(names)
  • printf(SCREEN,%s,Insert_IsSo(names[i],"funny"))
  • end for


Not sure if you are referring to the use of a cursors, the 'connect by level', or the use of a regular expression? Either way, all are standard PL/SQL in Oracle. But, given how much licenses cost, I'd say it is all enterprise :)

I'm by no means an accomplished programmer in this language, but I had to program in PLT Scheme (now Racket) in College. Scheme is a dialect of LISP.


  • #lang racket
  • (define names (list "Bob" "Lisa" "Bill" "Cindy"))
  • (define (nameAdjective adj namelist) (map (lambda (i) (string-append (string-append i " is so ") adj)) namelist))
  • (nameAdjective "stupid" names)

Hey guys, sorry I haven't picked any winners yet - things have been a bit crazy here. Will try to do this in the morning (I have a user-group meeting tonight).

Thanks again for all your submissions - this has been such an awesome turnout!

Bit late in the day but I thought it be good to see a Perl & Io solutions to the required spec.


  • my @names = qw/tom dick harry/;
  • sub add_adj {
  • my $adj = shift;
  • map "$_ is so $adj", @_;
  • }
  • my @new_names = add_adj( perlish => @names );

And Io:

  • names := list("Tom", "Dick", "Harry")
  • nameAdj := method (nameList, adj,
  • nameList map (name, "#{name} is so #{adj}" interpolate)
  • )
  • newNames := nameAdj(names, "Io-ish")


Or howbout in Fancy? :)

  • def names: names with_adjective: adj {
  • names map: |n| {
  • "#{n} is so #{adj}"
  • }
  • }
  • names: ["John", "Mike", "Alex", "Chris"] with_adjective: "cool" . println

Even though it's already over, here's one for Progress 4GL:

  • DEF VAR adjective AS CHAR NO-UNDO.
  • DEF TEMP-TABLE ttFullSentences NO-UNDO
  • FIELD sentence AS CHAR.
  • names = "Tiger Woods, Phil Mickelson, Rory McIlroy"
  • adjective = "much better at golfing than me".
  • RUN SetFullSentences(INPUT names,
  • INPUT adjective,
  • INPUT-OUTPUT TABLE ttFullSentences).
  • FOR EACH ttFullSentences:
  • ttFullSentences.sentence FORMAT "X(60)" LABEL "Sentences".
  • END.
  • PROCEDURE SetFullSentences:
  • DEF VAR sentenceFormat AS CHAR NO-UNDO INIT "&1 is so &2.".
  • EMPTY TEMP-TABLE ttFullSentences.
  • DO idx = 1 TO NUM-ENTRIES(namesList):
  • CREATE ttFullSentences.
  • sentence = SUBSTITUTE(sentenceFormat,
  • ENTRY(idx, namesList),
  • adjective).
  • END.
  • END. /* SetFullSentences */

There's been a couple of other .NET examples already, but just wanted to show extention methods and option query syntax for Linq. The query syntax is too verbose for a simple map (select) so I threw in the filter (where) clause. Also, the Dump method is a feature of the LINQPad scratch pad app.

void Main()
var names = new List<string> {"Bob", "Don", "Steve", "Bill"};

public static class Extensions
public static IEnumerable<string> Adj(this IEnumerable<string> names, string adjective)
return names.Select(name => string.Format("{0} is so {1}", name, adjective));

public static IEnumerable<string> AdjQuery(this IEnumerable<string> names, string adjective)
return from name in names
where name.Length > 3
select string.Format("{0} is so {1}", name, adjective);

Just to prove that there's always more than one way to do it in perl, here's an implementation that creates a list of anonymous subroutines in a function called gen and then returns and dispatches them.

  • sub gen {
  • $a=shift;
  • &{say "$_ is so $a"} for (@_);
  • }
  • $_->() for(@{gen('perlish'=>qw|tom dick harry|)});

I've enjoyed following your adventures in code, Ben and I'm now working my way through my own Seven Languages adventure at Cheers and congrats on finishing!