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