Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
F# enters Tiobe top 20 index for the first time (tiobe.com)
36 points by brs on Aug 8, 2011 | hide | past | favorite | 27 comments


Some F# to ponder:

    type LogicGate =
        | ON
        | OFF
        | NAND of LogicGate * LogicGate
        | NOT  of LogicGate
        | AND  of LogicGate * LogicGate
        | OR   of LogicGate * LogicGate
        | NOR  of LogicGate * LogicGate
        | XOR  of LogicGate * LogicGate
        | XNOR of LogicGate * LogicGate

    let rec evaluate input =
        match input with
        | ON         -> true
        | OFF        -> false
        | NAND(a, b) -> not ((evaluate a) && (evaluate b))
        | NOT(a)     -> (evaluate (NAND(a, a)))
        | AND(a, b)  -> (evaluate (NOT(NAND(a, b))))
        | OR(a, b)   -> (evaluate (NAND(NOT(a), NOT(b))))
        | NOR(a, b)  -> (evaluate (NOT(OR(a, b))))
        | XOR(a, b)  -> (evaluate (AND(NAND(a, b), OR(a, b))))
        | XNOR(a, b) -> (evaluate (NOT(XOR(a, b))))

    [
        NAND(OFF, OFF);
        NAND(OFF, ON);
        NAND(ON,  OFF);
        NAND(ON,  ON)
    ] |> List.map (fun x -> printfn (evaluate x))


While that's a very good example of what F# can do, I think the real value proposition of F# is that it can use anything from .NET. Take something like this for example:

  open System
  open System.Collections.Generic
  open System.Reflection
  
  type Config = string 
  type ISuperPlugin =
      abstract member Name : string
      abstract member Initialize : Config -> unit
  
  let loadedPlugins = Dictionary<string,ISuperPlugin>()
  
  let isPlugin (tp: Type) =
      tp.GetInterfaces()
      |> Seq.exists (fun t -> t.GetType() = typeof<ISuperPlugin>)
  
  let isPluginLoaded plugin =
      match loadedPlugins.TryGetValue(plugin) with
      | true, v -> true
      | _ -> false
  
  
  let loadPlugin typ = () // implement this
  
  let LoadPluginsFromAssembly path =
      let asm = Assembly.LoadFrom path
      asm.GetTypes()
      |> Seq.filter isPlugin
      |> Seq.filter (fun t -> not (isPluginLoaded t.Name))
      |> Seq.map loadPlugin
      |> ignore
  
  let loadAllPlugins plugins =
      plugins
      |> Seq.map (fun p -> async { LoadPluginsFromAssembly p })
      |> Async.Parallel
      |> ignore
Loads a bunch of plugins from assemblies in parallel. Haven't tested it but it should work with minor modifications to make it thread-safe.


The extra parentheses around the evaluates are not necessary, except in the last line. I'm fond of this pairing heap in F#:

    type 't heap = Empty | Heap of 't * 't heap list

    let findmin (Heap(x,_)) = x
    let merge h1 h2 = 
      match (h1,h2) with
      | Empty,h | h,Empty -> h
      | Heap(x,h1s),Heap(y,h2s) -> if x < y then Heap(x,h2::h1s) else Heap(y,h1::h2s)
    let deletemin (Heap(_,hs)) = List.fold merge Empty hs
    let insert h x = merge h (Heap(x,[]))


Equivalent C# code (if you want to appreciate the brevity of F# or just understand what the code is doing):

    public abstract class LogicGate
    {
        public abstract bool Evaluate();
    }

    public abstract class BinaryLogic : LogicGate
    {
        protected LogicGate a, b;
        
        public BinaryLogic(LogicGate a, LogicGate b)
        {
            this.a = a;
            this.b = b;
        }
    }

    public class ON : LogicGate
    {
        public override bool Evaluate() { return true; }
    }

    public class OFF : LogicGate
    {
        public override bool Evaluate() { return false; }
    }

    public class NAND : BinaryLogic
    {
        public NAND(LogicGate a, LogicGate b) : base(a, b) { }       

        public override bool Evaluate() 
        { 
            return !(a.Evaluate() && b.Evaluate()); 
        }
    }

    public class NOT : LogicGate
    {
        LogicGate a;

        public NOT(LogicGate a)
        {
            this.a = a;
        }

        public override bool Evaluate() 
        { 
            return new NAND(a, a).Evaluate(); 
        }
    }

    public class AND : BinaryLogic
    {
        public AND(LogicGate a, LogicGate b) : base(a, b) { }
      
        public override bool Evaluate() 
        { 
            return new NOT(new NAND(a, b)).Evaluate(); 
        }
    }

    public class OR : BinaryLogic
    {
        public OR(LogicGate a, LogicGate b) : base(a, b) { }
      
        public override bool Evaluate() 
        { 
            return new NAND(new NOT(a), new NOT(b)).Evaluate(); 
        }
    }

    public class NOR : BinaryLogic
    {
        public NOR(LogicGate a, LogicGate b) : base(a, b) { }
       
        public override bool Evaluate() 
        { 
            return new NOT(new OR(a, b)).Evaluate(); 
        }
    }

    public class XOR : BinaryLogic
    {
        public XOR(LogicGate a, LogicGate b) : base(a, b) { }
       
        public override bool Evaluate() 
        { 
            return new AND(new NAND(a, b), new OR(a, b)).Evaluate(); 
        }
    }

    public class XNOR : BinaryLogic
    {
        public XNOR(LogicGate a, LogicGate b) : base(a, b) { }     

        public override bool Evaluate() { return new NOT(new XOR(a, b)).Evaluate(); }
    }
   

    class Program
    {
        public static void Main(string[] args)
        {
            var on = new ON();
            var off = new OFF();
            
            var result = new List<LogicGate>() 
            { 
                new NAND(on, off), 
                new NAND(off, on), 
                new NAND(on, off), 
                new NAND(on, on) 
            }
            .Select(x => x.Evaluate());

            Console.WriteLine(result);
        }
        
     }


a bit rusty, but think this one's right too ( am using Peirce's arrow instead of Sheffer stroke )

type LogicGate = | ON | OFF | NOR of LogicGate * LogicGate | NOT of LogicGate | AND of LogicGate * LogicGate | OR of LogicGate * LogicGate | NAND of LogicGate * LogicGate | XOR of LogicGate * LogicGate | XNOR of LogicGate * LogicGate

    let rec evaluate input =
        match input with
        | ON         -> true
        | OFF        -> false
        | NOR(a, b) -> not ((evaluate a) || (evaluate b))
        | NOT(a)     -> (evaluate (NOR(a, a)))
        | OR(a, b)  -> (evaluate (NOT(NOR(a, b))))
        | AND(a, b)   -> (evaluate (NOR(NOT(a), NOT(b))))
        | NAND(a, b)  -> (evaluate (NOT(AND(a, b))))
        | XNOR(a, b)  -> (evaluate (OR(AND(a, b), NOR(a, b))))
        | XOR(a, b) -> (evaluate (NOT(XNOR(a, b))))

    [
        NOR(OFF, OFF);
        NOR(OFF, ON);
        NOR(ON,  OFF);
        NOR(ON,  ON)
    ] |> List.map (fun x -> printfn (evaluate x))


Curious: is this also valid ocaml?


Almost, |> isn't an operator in OCaml (although I think Batteries has something like |- that does the same thing) and printfn isn't in OCaml. Printf.printf is, but wouldn't work in this case (you'd need a format string). Also, List.map returns a new list, in OCaml you would probably want to do List.iter.


the |> operator is very very simple. ocaml implementation would look something like:

  let (|>) a b = b a ;;


From the full article:

The confidence of the SuperCollider programming language has been set to 80%. The reason for this is quite funny. In order to prove that the TIOBE index can be manipulated easily, Adam Kennedy created an empty Perl library called Acme-SuperCollider-Programming. This was to boost the unknown programming language SuperCollider by adding it to Perl's popular library archive CPAN. Now 20% of all +"SuperCollider programming" come from this artificial library.

Yes, quite funny indeed, but not for the reasons they think. Just to show that Tiobe methodology is a joke. I don't understand how people take this seriously.


Who has a better methodology? Is there even a good one?


If that was a serious question, places that do developer tools and programming languages for a living (at least MSFT, I assume others as well) pay ridiculous amounts of money to independent third-party companies that specialize in gathering this kind of data. The raw data was then kept fairly private (marketing + upper mgmt only), but the rank and file would see some of it occasionally when things such as trends on the number of VBA or VB5 or VC++ programmers appeared in slide decks talking about the direction for upcoming versions of the product.

Having working with the raw data, it was pretty fantastic. Segemented by industry/business size, handled issues with multiple programming languages or companies where one section used one language and another used other ones, etc. We even knew which tools and add-ons were used for which languages and which compiler on each platform (i.e. how many commercial shops using C++ targeting linux are using gcc vs. icc?).

But that data was also stunningly expensive. My marketing friends tell me that accurate market data always is.


Interesting. It's a tautology but the Internet sees only the Internet - there's a huge swathe of programming work that just isn't advertised online, so is invisible to TIOBE.


http://www.langpop.com is better because

1) I use more metrics and

2) I don't go around making statements about how, from one month to the next, someone displaced someone else, or climbed into a certain ranking, or things like that.

3) I let people reweight the chart based on the metrics they like.

I think the numbers LangPop comes up with are pretty good, but by their very nature are a bit fuzzy.


F# isn't listed on any of your charts. I think it's probably popular enough to show up in all of your data sources at this point.

Also, maybe add GitHub and StackOverflow as data sources?


F# should probably go there, yeah.

GitHub and StackOverflow started out really biased in terms of their communities - GitHub with Ruby, and StackOverflow with Microsoft languages. Do you think they've sufficiently lost that bias?


On another note, you know what else could be a great source(s) for data? Google Scholar, CiteSeerX and arXiv. It'd be really interesting to compare the language usage between "industry" and academia.


I think StackOverflow has; GitHub still seems a bit biased towards scripting languages like Ruby or Javascript though. In any case, since you show the graphs from the various sources, I don't think it matters if one source is more biased than another. If, for example, you used CodePlex as a data source, you'll see a huge bias towards C# -- but visitors to your site could simply draw their own conclusions from the charts.


Where can I see the data for GitHub?

I'm not sure I even trust that... I do lots of bindings from OCaml to C, and whereas I consider them to be OCaml projects, GitHub sees they're more C by LOC and counts them as C.


If nearly all ruby programmers put their code on github, and you don't count it but you do count google code, then isn't that a bias i the sample? Wouldn't it make more sense to include all the major code hosting sites, including github?


Google's Code Search just searches for code on the internet.


ah, sorry. I thought you were looking at google code repos.


This is, by the way, an honest question. I think at a certain point they'll be mainstream enough to say yes, but it's tough to say when.


Go was a winner of 2009, RPG (OS/400) is more popular than Haskell or Erlang. Sure this is a joke.


Actually the award Go won was "the highest rise in ratings in a year". That said, I do agree their methodology is pretty suspect. The thing is, a lot of developers look to Tiobe to decide what language to learn next, so it's interesting to follow even if the data is flawed.


The full article is at http://www.tiobe.com/index.php/content/paperinfo/tpci/index....

I couldn't put it in the submission because of HN's dupe detection.


I also look at the number of people in related Meetup and Linkedin groups. I'm in NYC and there are a lot of local people in various groups.


Scala ate their lunch.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: