Does one exist?
The closest I've found is - https://github.com/Antaris/RazorEngine ; but I'm not overjoyed by it (in particular, I can't get it to work.)
As requested in comments, T4 Text Templates (Run-Time Text Generation) is worth mentioning. Unfortunately, it seems only C# and VB.NET are supported as template languages, which means you'll have to create a separate C# project containing only templates and their backing models (e.g. DTO-like classes).
This project would be referenced and used by F# project. Good thing that such interop should be completely seamless :)
In addition to those mentioned by Patryk Ćwiek, I'd look at Fue.
Here's a basic template in Fue:
let html = "<div>{{{name}}}</div>"
let compiledHtml = init |> add "name" "Roman" |> fromText html
// compiledHtml now contains "<div>Roman</div>"
Fue is written in F# and has support for F# types such as options and Discriminated unions:
<!--Option types-->
<div fs-if="someOption.IsSome">{{{someOption.Value}}}</div>
<div fs-if="someOption.IsNone">Nothing</div>
<!--Discriminated Union
type UserAccess =
| Anonymous
| Admin of section:string
-->
<div fs-du="item" fs-case="Anonymous">Anonymous</div>
<div fs-du="item" fs-case="Admin(section)">{{{section}}}</div>
Fue on Github
Fue on Nuget
Related
Where I work we're still using Delphi 2009. I happened to be looking at the Forms unit in the VCL and stumbled upon:
[UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
function DisableTaskWindows(ActiveWindow: HWnd): TTaskWindowList;
This attribute is clearly the CLR class UIPermissionAttribute but unlike other references to the CLR this attribute is not wrapped in conditional compilation directives.
This surprised me because, AFAIK, in Delphi Win32 versions prior to 2010 brackets were only used for index notation in arrays and collection types, defining sets and assigning GUIDs to interfaces. This doesn't appear to be the case.
I did a regex search and found dozens of examples throughout the RTL/VCL. Some were attributes on types and some on methods.
Are these simply ignored by the compiler or do they serve some purpose in Win32?
I also found syntax that looked like:
[!UnitName]
[!InterfaceName]
Which appears to have something to do with generating source files from a template in an IDE wizard but these weren't in the RTL source folder. They were in the object repository folder.
I had hoped that perhaps attributes were an undocumented feature similar to how class helpers were available for years before they were documented but that doesn't appear to be the case.
I tried a simple test and added attribute notation before a class definition. The compiler didn't choke on it but it did issue a warning that custom attributes aren't supported.
It only recognizes top-level non-function value declarations.
e.g. let a = 2
and doesn't produce documentation for functions or type definitions.
I've checked the xml documentation file and it has all the /// comments I put in the source, but none of them (except for the top level values) show up in the resulting html.
Yes, using C#-centric tools for F# documentation generation is usually pretty horrible. We started an alternative project a while ago, but it is not yet as mature as SandCastle: http://bitbucket.org/IntelliFactory/if-doc
I'm trying to make an example I've found on the net work. It's a 3D fractal in F#. Here it is: http://tomasp.net/blog/infinite-cheese.aspx. The source code is available for download at the end of the article. The article and the sample were written in 2007, so I think the code is just slightly obsolete. There is one block of code that causes error and the code won't compile:
// Returns a cube with filtered sides
let private get_cube(incl_sides) =
[ for (side,trigs) in cube
when Set.mem side incl_sides
->> trigs ]
The when keyword is underlined, and the error message goes as follows:
Unexpected keyword 'when' in expression. Expected '->' or other token.
I can't figure out what's wrong with this. In an attempt to understand the code better, I searched the langauge specs. As far as I know, there is nothing about the Set.mem function or the ->> operator. Do you have any idea what could be wrong?
Try
[for (side, trigs) in cube do
if Set.contains side incl_sides then
yield! trigs]
The language has undergone a lot of changes since that code was written. In particular, the ->> operator has been replaced by yield!, Set.mem has been renamed to the more descriptive Set.contains, and comprehensions now use if ... then instead of when.
Yes, the version of the source code that is linked from the blog post is a bit old. You can find the latest (updated) version in the F# samples project on CodePlex. I think there may be some other changes, so it is best to get the version from CodePlex. (It includes FractalSimple.fs which is simpler version and Fractal.fs which also removes cube sides that are not visible).
The project contains standard Visual Studio 2008/2010 .fsproj project. The original version on the blog was written using F# CTP (from VS 2005 times) which had a completely different Visual Studio integration and used an obsolete .fsharpp project format (before MSBUILD format existed).
The when and ->> constructs have been used as a lightweight syntax for writing queries, but are now deprecated, to keep the syntax inside comprehensions consistent with the rest of the language. As kvb points out, you can use ordinary if .. then and the only non-standard thing is yield!, which means return all elements of the given sequence.
I want to make my Application configuration as F# file wich will be compiled to dll. (like XMonad configuration with xmonad.hs on haskell). I found it more interesting and just better way then using XML serialization.
So is there any way how can I compile single file (or more) to Library with some configuration like
module RNExcel.Repository
open RNExcel.Model
type ExpenseReportRepository() =
member x.GetAll() =
seq{ yield {Name="User1"
Role="someRole"
Password = "123321"
ExpenseLineItems =
[{ExpenseType="Item1"
ExpenseAmount="50"};
{ExpenseType="Item2"
ExpenseAmount="50"}]}
yield {Name="User2"
Role="Estimator"
Password = "123123"
ExpenseLineItems =
[{ExpenseType="Item1"
ExpenseAmount="50"};
{ExpenseType="Item2"
ExpenseAmount="125"}]} }
my idea was to run shell .... and msbuild the project , but I don't think it will works for every user with .net 4
Check out the F# Power Pack, specifically the FSharp.CodeDom library. You can use this library to compile F# code at run-time and, with a little Reflection thrown in, can likely achieve your goal of code-as-configuration with minimal fuss.
I think that using CodeDOM provider from the PowerPack as Ben suggested is a way to go. I'd just like to add a few things (and it didn't fit into the comment box).
To parse and compile the F# code with the configuration, you need just to compile the source file that the users write using F# PowerPack. The compilation part of PowerPack is complete and works just fine. It invokes the F# compiler under the cover and gives you the compiled assembly back. The only problem is that the users of your application will need to have F# compiler installed (and not just the redist).
The incomplete part of F# CodeDOM provider is generating F# code from CodeDOM trees (because the trees were not designed to support F#), but that's not needed in this case.
Are there any general localization/translation alternatives to gettext?
Open source or proprietary doesn't matter.
When I say alternative to gettext, I mean a library for internationalization, with a localization backend of sorts.
The reason I'm asking is because (among other things) I find the way gettext does things slightly cumbersome and static, mostly in the backend bit.
First of all I think gettext is one of the best at this point.
You may take a look on Boost.Locale that may provide a better API and use gettext's dictionary model: http://cppcms.sourceforge.net/boost_locale/docs/ (not official part of Boost, still beta).
Edit:
If you don't like gettext...
These are translation technologies:
OASIS XLIFF
GNU gettext po/mo files
POSIX catalogs
Qt ts/tm files
Java properties,
Windows resources.
Now:
Last two total crap... Very hard to use translate and maintain, do not support plural forms.
Qt ts/tm -- requires usage of Qt framework. Have very similar model to gettext. Not bad solution, but limited to Qt. Not so useful in generic programs.
POSIX catalogs -- nobody uses them, no plural forms support. Crap.
OASIX XLIFF -- "standard" solution, depends on XML, even ICU requires compilation to specific ICU resources for use. Limited translation tools, I don't know any library that supports XLIFF. Plural forms not so easy to use (ICU included some support only in 4.x release).
Now what do we have?
GNU gettext, widely used, has great tools, has great plural forms support, very popular in translators community...
So decide, do you really think that gettext is not so good solution?
I don't think so. You haven't worked with other solutions at all, so try to understand how it works at first place.
Fluent is a new system that offers a number of adaptations that gettext lacks. Where gettext supports pluralization, fluent has a generic framework for the text variants. Where gettext uses the "untranslated" string as its translation key, fluent supports an abstract key (allowing multiple translations for something that just happens to be homonymous in the source language. Here is a more extensive comparison.
An example of fluent .ftl file, taken from firefox's preferences codebase, looks like this:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
blocklist-window =
.title = Block Lists
.style = width: 55em
blocklist-description = Choose the list { -brand-short-name } uses to block online trackers. Lists provided by <a data-l10n-name="disconnect-link" title="Disconnect">Disconnect</a>.
blocklist-close-key =
.key = w
blocklist-treehead-list =
.label = List
blocklist-button-cancel =
.label = Cancel
.accesskey = C
blocklist-button-ok =
.label = Save Changes
.accesskey = S
# This template constructs the name of the block list in the block lists dialog.
# It combines the list name and description.
# e.g. "Standard (Recommended). This list does a pretty good job."
#
# Variables:
# $listName {string, "Standard (Recommended)."} - List name.
# $description {string, "This list does a pretty good job."} - Description of the list.
blocklist-item-list-template = { $listName } { $description }
blocklist-item-moz-std-listName = Level 1 block list (Recommended).
blocklist-item-moz-std-description = Allows some trackers so fewer websites break.
blocklist-item-moz-full-listName = Level 2 block list.
blocklist-item-moz-full-description = Blocks all detected trackers. Some websites or content may not load properly.
Interesting comments about gettext() and all those pro-gettext().
I'm not saying that it ain't working right in most cases, but I tried to manage one project with it and quickly felt overwhelm by the hardness of using it. Maybe there are a few user interfaces for translators today, but I did not even look. The extraction and merging of strings is just not doing it for me.
Now, I thank you Artyom for talking about XLIFF which is a much better solution for my environment since everything is XML. Oh! And there are excellent editors out there. But if you like gettext() you won't find them. 8-)
I'll suggest looking at this one for example:
https://sourceforge.net/projects/wordforge2/
Now, this may give the programmer a nightmare to make it all work, but what we want is a dream come true for the translators (and zero work by the programmer as translations pour in, because I can tell you that with gettext() I had to do all the work!)
There is an alternative from Zend that supports gettext *.po / *.mo files and many more formats.
Many Apache servers cache the translation files because gettext is implemented as a module and the server has to be restarted to refresh the translation data.
The Zend implementation avoids this and supports many more formats:
http://framework.zend.com/manual/1.12/en/zend.translate.html