public static boolean isValidExpression(String expression) {
Map<Character, Character> openClosePair = new HashMap<Character, Character>();
openClosePair.put(')', '(');
openClosePair.put('}', '{');
openClosePair.put(']', '[');
Stack<Character> stack = new Stack<Character>();
for(char ch : expression.toCharArray()) {
if(openClosePair.containsKey(ch)) {
if(stack.pop() != openClosePair.get(ch)) {
return false;
}
} else if(openClosePair.values().contains(ch)) {
stack.push(ch);
}
}
return stack.isEmpty();
}
У них разная семантика. Чтобы назвать один из них, Nullable - это идемпотентный конструктор данных, который работает только с типами значений, тогда как option - это обычный универсальный тип. Таким образом, у вас не может быть
Nullable<Nullable<int>>
, но у вас может быть
option<option<int>>
. Как правило, хотя есть некоторые перекрывающиеся сценарии, есть вещи, которые вы можете делать с одним, но не с другим.
Ключевое отличие состоит в том, что необходимо проверить тип параметра, чтобы увидеть, имеет ли он значение. См. Этот вопрос для хорошего описания его семантики: Как тип параметра работает в F #
Опять же, это из моего ограниченного понимания, но проблема, вероятно, заключается в том, как каждый из них отображается в IL. "Обнуляемая" структура, вероятно, обрабатывается несколько иначе, чем тип опции.
Вы обнаружите, что взаимодействие между различными языками .Net на самом деле сводится к тому, как визуализируется IL. В большинстве случаев он работает нормально, но иногда вызывает проблемы. ( проверьте это ). Как раз тогда, когда вы думали, что безопасно доверять уровню абстракции. :)
Из-за выбора представления времени выполнения для System.Nullable <'T>
.
Nullable пытается представить отсутствующие значения нулевым указателем и текущие значения указателями на эти значения.
(new System.Nullable<int>() :> obj) = null
|> printfn "%b" // true
(new System.Nullable<int>(1) :> obj).GetType().Name
|> printfn "%s" // Int32
Теперь рассмотрим строки. К сожалению, строки допускают значение NULL. Итак, это действительно:
null : string
Но теперь значение времени выполнения null
неоднозначно - оно может относиться либо к отсутствию значения, либо к наличию значения null
. По этой причине .NET не позволяет создавать System.Nullable
.
Сравните это с:
(Some (null : string) :> obj).GetType().Name
|> printfn "%s" // Option`1
При этом можно определить биекцию:
let optionOfNullable (a : System.Nullable<'T>) =
if a.HasValue then
Some a.Value
else
None
let nullableOfOption = function
| None -> new System.Nullable<_>()
| Some x -> new System.Nullable<_>(x)
Если вы наблюдаете за типами, эти функции ограничивают 'T
структурой и имеют конструктор с нулевым аргументом. Так что, возможно, компилятор F # сможет раскрыть.