F# Type Providers vs. Lisp macros

2019-04-04 02:29发布

问题:

I've been reading about F# 3.0 type providers (e.g. here) and it seems that they are based on a kind of compile-time code generation. In that respect I was wondering how they compare against Lisp macros. It would seem that both F# 3.0 type providers and Lisp macros allow user code to execute at compile time and introduce new types available to the compiler. Can anyone shed some light on the issue and nuances involved?

回答1:

There is some overlap between F# type providers and meta-programming techniques from other languages, but I agree with Daniel that they do not have much in common. F# has some other meta-programming techniques like quotations that are perhaps closer to LISP macros.

In particular:

  • LISP macros are typically used to transform expressions (you can take a LISP expression and either interpret it or transform it and then execute it). Note that the transformation takes a LISP expression as an input - on the other hand, type providers can only take very limited parameters (strings, integers).

  • Quotations are more similar. They can be used to process F# expression - you can treat a piece of F# code as data and interpret it or transform it. The transformation takes (a sub-set of) an F# expression, but it typically does not execute it.

  • Type providers are used purely to generate types. Since LISP is dynamically typed, this is not really a problem that you'd have in LISP. However, it is a sort of code-generation (a form of metaprogramming that you can certainly do in LISP).



回答2:

An interesting aspect of F# type providers is that they work not only at compile-time, but at design-time, that is, in a way that interacts with the full IDE tooling. Type Providers provide 'types' from an external schematized data source, but the implementation mechanism also enables lots of IDE tooling, including IntelliSense (identifier auto-completion), documentation, data tooltips, etc. Combined with the interactive REPL, this affords easy exploration of unfamiliar data sets in a way that is not quite like the experience in any other language.



回答3:

I'm not familiar with Lisp macros, but macros in general are used for meta programming (to save typing and add control constructs to the language). Type providers, on the other hand, generate strongly-typed APIs for external data sources.

I can't think of anything besides compile time "expansion" that they have in common.



回答4:

F# Type providers are a very specific case of compile time code generation i.e they are meant to solve a specific kind of problem by compile time code generation. They allow you to generate new types at compile time.

LISP macros are a more generic approach to meta-programming and hence cater to a lot of use cases. Macro's basically take input as S-expression (code or data) and emit other S-expression .

So a type provider can be implemented using macro easily, whereas you cannot cover the whole range of "what macros can do" with type providers.