Scala лучше печатает

Я часто ловлю себя на том, что делаю такие вещи, как:

println(foo)

когда я хочу сделать:

println foo

Компилятор этого не позволяет.

Кроме того, println — это полный рот, я просто хочу сказать:

echo foo

Итак, в объекте базового пакета я создал эхо-версию println:

def echo(x: Any) = Console.println(x)

Достаточно просто, широкое эхо-приложение, отлично.

Теперь, как мне вызвать эхо без необходимости заключать Any для печати в круглые скобки?


person virtualeyes    schedule 09.04.2012    source источник
comment
возможный дубликат Почему я не могу написать println Hello world в Scala ?   -  person Debilski    schedule 09.04.2012
comment
@Debilski - это вопрос «Как мне быть», который выявил несколько отличных, хотя и пугающих, хаков. Другой вопрос: почему я не могу , чей ответ дает отличное объяснение основной проблемы. Я голосую против закрытия.   -  person leedm777    schedule 09.04.2012
comment
@dave: ты прав. Его нужно было закрыть задолго до того, как можно было опубликовать эти пугающие взломы.   -  person Debilski    schedule 09.04.2012
comment
и все же его не следует закрывать, потому что вопрос нацелен на сам println, а не только на вызов без скобок.   -  person virtualeyes    schedule 09.04.2012
comment
@virtualeyes: Может быть. Но, с другой стороны, такой вопрос, как «Разве «echo» не является более подходящей командой, чем «println», как вы думаете?» может легко получить тег «неконструктивный».   -  person Debilski    schedule 09.04.2012
comment
правда, но опять же, это может также вызвать вопрос, почему я все время набираю 7 символов, когда я могу выразить одно и то же намерение в 4 символах?   -  person virtualeyes    schedule 09.04.2012


Ответы (5)


object ∊ {def cho(s: Any) {println(s)}}

∊cho "Hello world"

спасет ваши пальцы.

Это работает, потому что ∊ является математическим символом в наборе Unicode Sm, поэтому считается оператором в Scala., поэтому не требует пробелов при размещении рядом с буквенно-цифровыми символами.

Вы также можете

object echo {def -(s: Any) {println(s)}}

echo-"Hello world"

который работает очень хорошо IMO.

ГОДЫ СПУСТЯ EDIT: еще одно почти решение, использующее StringContext:

implicit class PimpMyString(sc: StringContext) {
  def echo(args: Any*) = println(sc.raw(args: _*))
}

echo"Hello World"
person Luigi Plinge    schedule 09.04.2012
comment
интересно, однако, немного многовато ;-) Прямое echo(foo) нормально, как и println(foo), если бы мне не нужно было вводить все это (автозаполнение IDE, выбор из списка на самом деле медленнее, чем просто молоток вышло, кстати) - person virtualeyes; 09.04.2012
comment
Почему не cout<<"Hello world"? - person Debilski; 10.04.2012
comment
теперь единственная проблема состоит в том, чтобы выяснить, как набирать быстрее, чем набирать скобки. - person Jus12; 10.04.2012

Определять

trait ShortCuts {
  def echo(x: Any) = Console.println(x)
  def trace[T](x: T): T = { echo(x); x }
  // ...
}

object ↬ extends ShortCuts

и используйте счастливо без круглых скобок:

↬ echo "hello!"
person Debilski    schedule 09.04.2012
comment
k, поймите, println, echo, что угодно, у вас должен быть контекст, чтобы вызывать без скобок. - person virtualeyes; 09.04.2012
comment
не работает: ‹консоль›:1: ошибка: ';' ожидается, но найден целочисленный литерал. - person Alex B; 17.05.2018

Scalaz имеет расширенный тип Identity с println.

scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._

scala> val foo = 1
foo: Int = 1

scala> foo println
1

Если вы не хотите зависеть от scalaz, вы можете создать свою собственную прокачанную идентификацию и поместить неявную для нее в объект пакета.

person huynhjl    schedule 09.04.2012
comment
правильно, я фактически начал с неявного перед клонированием println из PreDef. Смотрите мою обновленную альтернативу - person virtualeyes; 09.04.2012

То, чего вы пытаетесь достичь, невозможно в Scala.

Скобки можно отбрасывать только в так называемом синтаксисе без точек, в котором у вас должен быть объект контекста в левой части функции, поэтому в вашем случае вы можете добиться только следующего, что в любом случае не имеет никакого смысла:

Console println x

Хотя я понимаю, почему вы хотите добиться этого, вероятно, учитывая более простые синтаксические конструкции других языков, я бы посоветовал просто придерживаться стандартного способа Scala, поэтому просто используйте println(x) или рассмотрите другие языки. Создание метода делегирования для такой базовой стандартной функции определенно принесет вам только проблемы в будущем управлении вашими проектами - так что однозначно "нет-нет" методу echo.

Для таких случаев есть старая поговорка: в Риме поступай как римляне.

person Nikita Volkov    schedule 09.04.2012
comment
Спасибо, не вижу здесь опасности. Я ничего не делегирую, нет накладных расходов, просто метод в объекте базового пакета. Если в будущем Scala/Java будет работать с чем-то другим, кроме Console.println(), есть колоссальное 1 место, где можно внести изменения. Что касается рассмотрения других языков, основанных на моем стремлении к альтернативе для печати, не знаю, что сказать. Scala полностью и полностью качается, должен ли я использовать PHP вместо Scala, основываясь на том факте, что они используют эхо? ;-) - person virtualeyes; 09.04.2012
comment
@virtualeyes Вероятность того, что JVM нарушит обратную совместимость, приближается к нулю. Существует гораздо большая вероятность того, что некоторые люди, работающие с вашим кодом, не поймут, что происходит, пока не изучат ваши настройки по сравнению со стандартными API. Есть даже неплохая вероятность, что через какое-то время у вас самих возникнут проблемы с пониманием этого кода. Кроме того, после того, как вы привыкнете к своим собственным API, вам будет гораздо труднее понять код, который вы не писали. И определенно такие вещи не будут высоко оценены командой, если вам когда-либо придется работать в ней. - person Nikita Volkov; 09.04.2012
comment
@virtualeyes Из других языков вы могли бы рассмотреть Haskell, если вы ищете функциональный статический язык с отличным синтаксисом, Python, если вы ищете популярный язык с хорошим синтаксисом (или Jython, если вы нацелены на JVM). Есть также новорожденный Kotlin, который является своего рода улучшенным и упрощенным Scala — поскольку это продукт JetBrains, он определенно станет популярным и будет иметь превосходную поддержку IDE. Языки, которые я только что назвал, доминируют над Scala в соответствующих областях. Я бы никогда не советовал даже прикасаться к PHP. - person Nikita Volkov; 09.04.2012
comment
да, аспект команды является хорошим моментом, а также взаимодействие/знакомство/конвенция Java. Обычно мне было бы все равно, но операторы println — настолько распространенная задача разработки, что я готов поэкспериментировать с более короткой формой, эхом. Само собой разумеется, что я выступаю в одиночку, проектирую базу данных для кодирования, поэтому беспокоить членов команды не будет проблемой (по крайней мере, сейчас). - person virtualeyes; 09.04.2012
comment
Конечно, есть много отличных языков, ну и что? То, что я предпочитаю echo, а не println, не означает, что я должен отказаться от Scala. Хорошая вещь в Scala заключается в том, что у вас есть свобода действий, чтобы делать все, что вам заблагорассудится, как Ruby, но с проверенным компилятором кодом, IMO, лучшим из обоих миров. Согласен, Kotlin выглядит новичком в JVM, но им предстоит пройти долгий путь, чтобы догнать Scala. Новый язык не приходит без вопросов/проблем/и т.д. (конечно, Kotlin может использовать каждую функцию Scala в книге и избежать ловушек, из-за опоздания на вечеринку) - person virtualeyes; 09.04.2012
comment
@virtualeyes Любая современная IDE и даже такие редакторы, как Sublimetext, имеют функцию шаблонов — вы можете просто создать шаблон pl, который будет разворачиваться в оператор println и запускать его тремя штрихами (даже меньше, чем нужно для ввода echo): p-l-TAB. Я сам так сделал. В настоящее время создание шаблонов является распространенным подходом к сокращению набора текста на любом языке. - person Nikita Volkov; 09.04.2012
comment
Да, идея фрагмента была тем, о чем я впервые подумал, новичок в Eclipse и еще не покопался в этом варианте. Очевидно, что сам по себе println не так уж и шумит, гораздо меньше, чем Console.println и System.out.println и прочее безумие ;-) - person virtualeyes; 09.04.2012
comment
Интересно, что Python начал требовать круглые скобки, когда они перешли на версию 3: вместо print "x" в Python 2 нужно было писать print ("x"). Причина в том, что, работая как любая другая функция, язык более регулярен. - person Luigi Plinge; 09.04.2012
comment
вы можете прокачать эхо на Any и обойти необходимость в скобках - person virtualeyes; 09.04.2012
comment
@virtualeyes: (Конечно, это зависит от варианта использования и того, как вы пишете код разработки, но) большинство применений println можно безопасно заменить некоторыми командами ведения журнала, большинство из которых, если не все, даже немного короче. debug, info… ;) - person Debilski; 10.04.2012

Здесь представлен интересный набор ответов, начиная от «это невозможно» и заканчивая «это можно сделать» с помощью этого хака, зависящего от символов, или с этой зависимостью (Scalaz).

@Nikita правильно указывает, что можно так же легко добавить фрагмент в свою IDE (если вы так работаете), который выполняет println «работу ногами». Хотя это правда, вам обычно нужно перестать печатать, чтобы нажать ctrl-p-r или любую комбинацию клавиш, которую вы решите использовать, что нарушает ваш поток, IMO. Итак, в духе создания «лучшего» println, вот что я думаю:

Создайте объект базового пакета, от которого будут наследоваться ваши подпакеты (модель, представление, дао и т. д.) (в основном ваш собственный PreDef)

package com
package object company {

  // echo(foo)
  def echo(x: Any) = Console.println(x)

  // foo.echo   
  class AnyProvidesEcho(x: Any) { def echo = Console.println(x) }
  @inline implicit def any2Echo(x: Any) = new AnyProvidesEcho(x)
}

Использование:

val list = List(1,2,3)
val string = "c'est beacoup mieux mit butter"

list foreach echo
echo(string)
string.echo
person virtualeyes    schedule 09.04.2012
comment
Пока вы это делаете, вы должны добавить trace, который печатает и возвращает значение. - person Debilski; 10.04.2012