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))
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 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.
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.
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.
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.
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?
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.