Hacker News new | ask | show | jobs
F# enters Tiobe top 20 index for the first time (tiobe.com)
36 points by brs 5424 days ago
6 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.
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);
        }
        
     }
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,[]))
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.
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?
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.