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?
相关问题
- F#: Storing and mapping a list of functions
- I want to trace logs using a Macro multi parameter
- Does powershell have a method_missing()?
- Generating powerset in one function, no explicit r
- Objective-C dynamically created methods and compil
相关文章
- Macro expansion in elixir: how to define 2 macros
- FSharp.Data.JsonProvider - Getting json from types
- Signing an F# Assembly (Strong name component)
- Learning F#: What books using other programming la
- fsc.exe is very slow because it tries to access cr
- How to import macros in Rust?
- Does learning one Lisp help in learning the other?
- Using C Preprocessing to get integer value of a st
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.
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.
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.
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).