├── .gitignore ├── .ruby-version ├── README.mkdn ├── Rakefile ├── app ├── controllers │ ├── application.rb │ └── learn_controller.rb └── helpers │ ├── application_helper.rb │ └── learn_helper.rb ├── config ├── boot.rb ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── inflections.rb │ └── mime_types.rb └── routes.rb ├── doc └── httpd_conf_changes ├── index.rb ├── lib ├── learn_to_program_tutorial.rb └── learn_to_program_tutorial │ ├── arrays.rb │ ├── beyond.rb │ ├── blocks_procs.rb │ ├── classes.rb │ ├── conversion.rb │ ├── def_methods.rb │ ├── flow_control.rb │ ├── formatting_page.rb │ ├── learn_to_program.rb │ ├── letters.rb │ ├── main.rb │ ├── menu.rb │ ├── methods.rb │ ├── numbers.rb │ ├── setup.rb │ └── variables.rb ├── log └── .gitignore ├── public ├── .htaccess ├── 404.html ├── 422.html ├── 500.html ├── SciTEGlobal.properties ├── dispatch.cgi ├── dispatch.fcgi ├── dispatch.rb ├── favicon.ico ├── images │ ├── LTP_cover.jpg │ ├── PoweredByRuby.png │ ├── fleur_right.gif │ ├── flowerborder.gif │ ├── locketLTP.png │ ├── paper_background.png │ ├── rails.png │ ├── shadowS.gif │ ├── speardown_sm.gif │ ├── spearup_sm.gif │ ├── swirly.gif │ ├── titleLTP.gif │ └── titleLTP_pt_br.gif ├── robots.txt ├── ruby.properties └── stylesheets │ ├── pine.css │ ├── print.css │ └── tutorial.css ├── script ├── about ├── console ├── destroy ├── generate ├── performance │ ├── benchmarker │ ├── profiler │ └── request ├── plugin ├── process │ ├── inspector │ ├── reaper │ └── spawner ├── runner └── server └── test ├── functional └── learn_controller_test.rb └── test_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | tmp 3 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 1.8.7-p375 2 | 3 | -------------------------------------------------------------------------------- /README.mkdn: -------------------------------------------------------------------------------- 1 | Aprenda a Programar 2 | ================== 3 | Leia a introdução deste projeto em [Aprenda a Programar](http://aprendaaprogramar.rubyonrails.com.br/). 4 | 5 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require(File.join(File.dirname(__FILE__), 'config', 'boot')) 5 | 6 | require 'rake' 7 | require 'rake/testtask' 8 | require 'rake/rdoctask' 9 | 10 | require 'tasks/rails' 11 | -------------------------------------------------------------------------------- /app/controllers/application.rb: -------------------------------------------------------------------------------- 1 | # Filters added to this controller apply to all controllers in the application. 2 | # Likewise, all the methods added will be available for all controllers. 3 | 4 | class ApplicationController < ActionController::Base 5 | helper :all # include all helpers, all the time 6 | 7 | # See ActionController::RequestForgeryProtection for details 8 | # Uncomment the :secret if you're not using the cookie session store 9 | protect_from_forgery # :secret => '4e5c7c32a50dfd87987cb232b1cc3de5' 10 | end 11 | -------------------------------------------------------------------------------- /app/controllers/learn_controller.rb: -------------------------------------------------------------------------------- 1 | class LearnController < ApplicationController 2 | session :off 3 | 4 | def index 5 | # captura a saída 6 | request.cgi.instance_eval do 7 | def out(options = 'text/plain', optional = true) 8 | yield if block_given? 9 | end 10 | end 11 | opt = {} 12 | 13 | # reajusta os parâmetros para passar ao CGI 14 | params.each { |k,v| opt.merge!( k => [v] ) } 15 | unless opt.include?("ShowTutorialCode") 16 | opt.merge!("ShowTutorialCode" => [nil]) 17 | end 18 | unless opt.include?("Chapter") 19 | opt.merge!("Chapter" => 13) 20 | end 21 | request.cgi.params = opt 22 | 23 | # redireciona a saída do cgi para a saída do controller 24 | render :text => LearnToProgramTutorial.handle_request(request.cgi), :status => 200, :layout => false 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | # Methods added to this helper will be available to all templates in the application. 2 | module ApplicationHelper 3 | end 4 | -------------------------------------------------------------------------------- /app/helpers/learn_helper.rb: -------------------------------------------------------------------------------- 1 | module LearnHelper 2 | end 3 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | # Don't change this file! 2 | # Configure your app in config/environment.rb and config/environments/*.rb 3 | 4 | RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT) 5 | 6 | module Rails 7 | class << self 8 | def boot! 9 | unless booted? 10 | preinitialize 11 | pick_boot.run 12 | end 13 | end 14 | 15 | def booted? 16 | defined? Rails::Initializer 17 | end 18 | 19 | def pick_boot 20 | (vendor_rails? ? VendorBoot : GemBoot).new 21 | end 22 | 23 | def vendor_rails? 24 | File.exist?("#{RAILS_ROOT}/vendor/rails") 25 | end 26 | 27 | # FIXME : Ruby 1.9 28 | def preinitialize 29 | load(preinitializer_path) if File.exists?(preinitializer_path) 30 | end 31 | 32 | def preinitializer_path 33 | "#{RAILS_ROOT}/config/preinitializer.rb" 34 | end 35 | end 36 | 37 | class Boot 38 | def run 39 | load_initializer 40 | Rails::Initializer.run(:set_load_path) 41 | end 42 | end 43 | 44 | class VendorBoot < Boot 45 | def load_initializer 46 | require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer" 47 | end 48 | end 49 | 50 | class GemBoot < Boot 51 | def load_initializer 52 | self.class.load_rubygems 53 | load_rails_gem 54 | require 'initializer' 55 | end 56 | 57 | def load_rails_gem 58 | if version = self.class.gem_version 59 | gem 'rails', version 60 | else 61 | gem 'rails' 62 | end 63 | rescue Gem::LoadError => load_error 64 | $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.) 65 | exit 1 66 | end 67 | 68 | class << self 69 | def rubygems_version 70 | Gem::RubyGemsVersion if defined? Gem::RubyGemsVersion 71 | end 72 | 73 | def gem_version 74 | if defined? RAILS_GEM_VERSION 75 | RAILS_GEM_VERSION 76 | elsif ENV.include?('RAILS_GEM_VERSION') 77 | ENV['RAILS_GEM_VERSION'] 78 | else 79 | parse_gem_version(read_environment_rb) 80 | end 81 | end 82 | 83 | def load_rubygems 84 | require 'rubygems' 85 | 86 | unless rubygems_version >= '0.9.4' 87 | $stderr.puts %(Rails requires RubyGems >= 0.9.4 (you have #{rubygems_version}). Please `gem update --system` and try again.) 88 | exit 1 89 | end 90 | 91 | rescue LoadError 92 | $stderr.puts %(Rails requires RubyGems >= 0.9.4. Please install RubyGems and try again: http://rubygems.rubyforge.org) 93 | exit 1 94 | end 95 | 96 | def parse_gem_version(text) 97 | $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/ 98 | end 99 | 100 | private 101 | def read_environment_rb 102 | File.read("#{RAILS_ROOT}/config/environment.rb") 103 | end 104 | end 105 | end 106 | end 107 | 108 | # All that for this: 109 | Rails.boot! 110 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file 2 | 3 | # Uncomment below to force Rails into production mode when 4 | # you don't control web/app server and can't set it the proper way 5 | # ENV['RAILS_ENV'] ||= 'production' 6 | 7 | # Specifies gem version of Rails to use when vendor/rails is not present 8 | RAILS_GEM_VERSION = '2.0.5' unless defined? RAILS_GEM_VERSION 9 | 10 | # Bootstrap the Rails environment, frameworks, and default configuration 11 | require File.join(File.dirname(__FILE__), 'boot') 12 | 13 | Rails::Initializer.run do |config| 14 | # Settings in config/environments/* take precedence over those specified here. 15 | # Application configuration should go into files in config/initializers 16 | # -- all .rb files in that directory are automatically loaded. 17 | # See Rails::Configuration for more options. 18 | 19 | # Skip frameworks you're not going to use (only works if using vendor/rails). 20 | # To use Rails without a database, you must remove the Active Record framework 21 | config.frameworks -= [ :active_record, :active_resource, :action_mailer ] 22 | 23 | # Only load the plugins named here, in the order given. By default, all plugins 24 | # in vendor/plugins are loaded in alphabetical order. 25 | # :all can be used as a placeholder for all plugins not explicitly named 26 | # config.plugins = [ :exception_notification, :ssl_requirement, :all ] 27 | 28 | # Add additional load paths for your own custom dirs 29 | config.load_paths += %W( #{RAILS_ROOT}/lib/learn_to_program_tutorial ) 30 | 31 | # Force all environments to use the same logger level 32 | # (by default production uses :info, the others :debug) 33 | # config.log_level = :debug 34 | 35 | # Your secret key for verifying cookie session data integrity. 36 | # If you change this key, all old sessions will become invalid! 37 | # Make sure the secret is at least 30 characters and all random, 38 | # no regular words or you'll be exposed to dictionary attacks. 39 | config.action_controller.session = { 40 | :session_key => '_learn_session', 41 | :secret => '041651ad6dc9bfe12a701d60b0575aa2688ed44df336e1ba9658a932464eda4e5476c53966ac3fdfdf21fc5399053cf3aa40da6bc6ba76c0074f82af4b721661' 42 | } 43 | 44 | # Use the database for sessions instead of the cookie-based default, 45 | # which shouldn't be used to store highly confidential information 46 | # (create the session table with 'rake db:sessions:create') 47 | # config.action_controller.session_store = :active_record_store 48 | 49 | # Use SQL instead of Active Record's schema dumper when creating the test database. 50 | # This is necessary if your schema can't be completely dumped by the schema dumper, 51 | # like if you have constraints or database-specific column types 52 | # config.active_record.schema_format = :sql 53 | 54 | # Activate observers that should always be running 55 | # config.active_record.observers = :cacher, :garbage_collector 56 | 57 | # Make Active Record use UTC-base instead of local time 58 | # config.active_record.default_timezone = :utc 59 | end 60 | require 'learn_to_program_tutorial' -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | # Settings specified here will take precedence over those in config/environment.rb 2 | 3 | # In the development environment your application's code is reloaded on 4 | # every request. This slows down response time but is perfect for development 5 | # since you don't have to restart the webserver when you make code changes. 6 | config.cache_classes = false 7 | 8 | # Log error messages when you accidentally call methods on nil. 9 | config.whiny_nils = true 10 | 11 | # Show full error reports and disable caching 12 | config.action_controller.consider_all_requests_local = true 13 | config.action_view.debug_rjs = true 14 | config.action_controller.perform_caching = false 15 | config.action_view.cache_template_extensions = false 16 | 17 | # Don't care if the mailer can't send 18 | config.action_mailer.raise_delivery_errors = false -------------------------------------------------------------------------------- /config/environments/production.rb: -------------------------------------------------------------------------------- 1 | # Settings specified here will take precedence over those in config/environment.rb 2 | 3 | # The production environment is meant for finished, "live" apps. 4 | # Code is not reloaded between requests 5 | config.cache_classes = true 6 | 7 | # Use a different logger for distributed setups 8 | # config.logger = SyslogLogger.new 9 | 10 | # Full error reports are disabled and caching is turned on 11 | config.action_controller.consider_all_requests_local = false 12 | config.action_controller.perform_caching = true 13 | config.action_view.cache_template_loading = true 14 | 15 | # Enable serving of images, stylesheets, and javascripts from an asset server 16 | # config.action_controller.asset_host = "http://assets.example.com" 17 | 18 | # Disable delivery errors, bad email addresses will be ignored 19 | # config.action_mailer.raise_delivery_errors = false 20 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | # Settings specified here will take precedence over those in config/environment.rb 2 | 3 | # The test environment is used exclusively to run your application's 4 | # test suite. You never need to work with it otherwise. Remember that 5 | # your test database is "scratch space" for the test suite and is wiped 6 | # and recreated between test runs. Don't rely on the data there! 7 | config.cache_classes = true 8 | 9 | # Log error messages when you accidentally call methods on nil. 10 | config.whiny_nils = true 11 | 12 | # Show full error reports and disable caching 13 | config.action_controller.consider_all_requests_local = true 14 | config.action_controller.perform_caching = false 15 | 16 | # Disable request forgery protection in test environment 17 | config.action_controller.allow_forgery_protection = false 18 | 19 | # Tell ActionMailer not to deliver emails to the real world. 20 | # The :test delivery method accumulates sent emails in the 21 | # ActionMailer::Base.deliveries array. 22 | config.action_mailer.delivery_method = :test 23 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format 4 | # (all these examples are active by default): 5 | # Inflector.inflections do |inflect| 6 | # inflect.plural /^(ox)$/i, '\1en' 7 | # inflect.singular /^(ox)en/i, '\1' 8 | # inflect.irregular 'person', 'people' 9 | # inflect.uncountable %w( fish sheep ) 10 | # end 11 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | # Mime::Type.register_alias "text/html", :iphone 6 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | ActionController::Routing::Routes.draw do |map| 2 | map.root :controller => 'learn' 3 | map.connect 'index.rb', :controller => 'learn', :action => 'index' 4 | end 5 | -------------------------------------------------------------------------------- /doc/httpd_conf_changes: -------------------------------------------------------------------------------- 1 | # colocar no seu httpd.conf 2 | # no mac, o path é /private/etc/httpd/users/nome_do_usuario.conf 3 | # 4 | # Alterar LINKADDR no learn_to_program_tutorial.rb de acordo com seu ambiente 5 | 6 | AddHandler cgi-script .rb 7 | 8 | 9 | Options Indexes MultiViews ExecCGI 10 | AllowOverride None 11 | Order allow,deny 12 | Allow from all 13 | 14 | -------------------------------------------------------------------------------- /index.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'cgi' 4 | require 'stringio' 5 | require 'learn_to_program_tutorial' 6 | 7 | cgi = CGI.new 8 | 9 | LearnToProgramTutorial.handle_request cgi -------------------------------------------------------------------------------- /lib/learn_to_program_tutorial.rb: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby 2 | 3 | 4 | #-----------------------------------------------# 5 | # Learn to Program # 6 | # by Chris Pine # 7 | # Copyright (c) 2003-2006 # 8 | # chris@pine.fm # 9 | #-----------------------------------------------# 10 | 11 | 12 | require 'cgi' 13 | require 'stringio' 14 | 15 | Dir.glob(File.dirname(__FILE__) + '/learn_to_program_tutorial/*').each { |file| require_dependency file } 16 | 17 | LINKADDR = '/' 18 | FRLTP_ADDR = 'http://pragmaticprogrammer.com/titles/fr_ltp' 19 | 20 | HLINE = '
 
' 21 | 22 | # If you decide to change coloring or formatting of this tutorial, 23 | # you'll want to change these to something appropriate. 24 | NUMBER_COLOR = 'verde' 25 | STRING_COLOR = 'vermelho' 26 | KEYWORD_COLOR = 'azul' 27 | INPUT_DESC = 'caixa branca' 28 | OUTPUT_DESC = 'caixa azul' 29 | 30 | # Delimiter for input to sample code, since it comes out 31 | # right alongside the output. Must not be html escapable. 32 | INPUT = "%%%'f'o'o'" 33 | 34 | class LearnToProgramTutorial 35 | @@NUMBER_COLOR = NUMBER_COLOR 36 | @@STRING_COLOR = STRING_COLOR 37 | @@KEYWORD_COLOR = KEYWORD_COLOR 38 | @@INPUT_DESC = INPUT_DESC 39 | @@OUTPUT_DESC = OUTPUT_DESC 40 | 41 | include LearnToProgram 42 | include FormattingPage 43 | include Setup 44 | include Numbers 45 | include Letters 46 | include Variables 47 | include Conversion 48 | include Methods 49 | include FlowControl 50 | include Arrays 51 | include DefMethods 52 | include Classes 53 | include BlocksProcs 54 | include Beyond 55 | 56 | include Menu 57 | include Main 58 | end 59 | -------------------------------------------------------------------------------- /lib/learn_to_program_tutorial/arrays.rb: -------------------------------------------------------------------------------- 1 | module Arrays 2 | # 3 | # ARRAYS AND ITERATORS 4 | # 5 | 6 | def generateArrays 7 | para do <<-END_PARAGRAPH 8 | Vamos escrever um programa que nos permita entrar com quantas 9 | palavras quisermos (uma por linha, até pressionarmos Enter 10 | em uma linha vazia), e depois mostre as palavras em ordem alfabética. Ok? 11 | END_PARAGRAPH 12 | end 13 | para do <<-END_PARAGRAPH 14 | Então... primeiro nós iremos.. bem.. hum... Bom, poderíamos.. rsrsrs.. 15 | END_PARAGRAPH 16 | end 17 | para do <<-END_PARAGRAPH 18 | Certo, não sei se podemos fazer isso. Precisamos de uma forma de armazenar 19 | um número qualquer de palavras, e de podermos acessá-las sem que se misturem 20 | com as outras variáveis. Precisamos colocá-las num tipo de lista. Precisamos 21 | dos arrays. 22 | END_PARAGRAPH 23 | end 24 | para do <<-END_PARAGRAPH 25 | Um array é apenas uma lista em seu computador. Cada item da lista 26 | se comporta como uma variável: você pode ver qual objeto um item está 27 | apontando, e você pode fazê-lo apontar para um outro objeto. 28 | Vamos dar uma olhada em alguns arrays: 29 | END_PARAGRAPH 30 | end 31 | prog false do <<-END_CODE 32 | [] 33 | [5] 34 | ['Olá', 'Tchau'] 35 | 36 | sabor = 'baunilha' # isto não é um array, claro... 37 | [89.9, sabor, [true, false]] # ...mas isto é. 38 | END_CODE 39 | end 40 | para do <<-END_PARAGRAPH 41 | Primeiro nós temos um array vazio, então um array contendo 42 | um único número, então um array contendo duas strings. 43 | Depois, temos uma atribuição simples; e aí um array 44 | contendo três objetos, sendo que o último é um outro 45 | array #{code '[true, false]'}. Lembre-se, variáveis não 46 | são objetos, então, nosso último array está realmente 47 | apontando a para um float, uma string e um array. 48 | Mesmo que nós mudássemos o valor de #{code 'sabor'}, isso 49 | não mudaria o array. 50 | END_PARAGRAPH 51 | end 52 | para do <<-END_PARAGRAPH 53 | Para nos ajudar a encontrar um objeto qualquer num array, 54 | cada item tem um número de indexação. Programadores (e, aliás, 55 | a maioria dos matemáticos) iniciam contando do zero, então, 56 | o primeiro item do array é o item zero. Veja como podemos 57 | referenciar os objetos em um array: 58 | END_PARAGRAPH 59 | end 60 | prog do <<-END_CODE 61 | nomes = ['Ana', 'Maria', 'Cris'] 62 | 63 | puts nomes 64 | puts nomes[0] 65 | puts nomes[1] 66 | puts nomes[2] 67 | puts nomes[3] # Isto está fora do intervalo 68 | END_CODE 69 | end 70 | para do <<-END_PARAGRAPH 71 | Vemos então, que #{code 'puts nomes'} imprime cada nome do 72 | array #{code 'nomes'}. Então usamos #{code 'puts nomes[0]'} 73 | para imprimir o "primeiro" nome do array e #{code 'puts nomes[1]'} 74 | para imprimir o "segundo"... Tenho certeza que parece confuso, 75 | mas você deve se acostumar com isso. Você deve realmente 76 | começar a acreditar que contar inicia do zero e parar 77 | de usar palavras como "primeiro" e "segundo". 78 | Se você for num rodízio de pizza, não fale sobre o "primeiro" 79 | pedaço; fale sobre o pedaço zero (e na sua cabeça 80 | pense #{code 'pedaco[0]'}). 81 | Você tem 5 dedos na sua mão e seus números são 0, 1, 2, 3 e 4. 82 | Minha esposa e eu somos malabariastas. Quando fazemos malabares 83 | com 6 pinos, estamos equilibrando os pinos 0 a 5. Felizmente, 84 | em alguns meses, estaremos equilibrando o pino 6 (e portanto, 85 | equilibrando 7 pinos). Você saberá que conseguiu quando 86 | começar a usar o termo "zerésimo" :-) Sim, é uma palavra real.. 87 | Pergunte a um programador ou matemático.. 88 | END_PARAGRAPH 89 | end 90 | para do <<-END_PARAGRAPH 91 | Finalmente, nós tentamos #{code 'puts nomes[3]'}, apenas veja o que 92 | aconteceria. Você estava esperando um erro? Algumas vezes quando 93 | você faz uma pergunta, sua pergunta não faz sentido (pelo 94 | menos para seu computador); é quando obtém um erro. 95 | Algumas vezes, entretanto, você pode fazer uma pergunta e a resposta 96 | é nada. O que está na posição três? Nada. 97 | O que é #{code 'nomes[3]'}? #{code 'nil'}: A maneira Ruby 98 | de dizer "nada". #{code 'nil'} é um objeto especial 99 | que basicamente significa "não é qualquer outro objeto." 100 | END_PARAGRAPH 101 | end 102 | para do <<-END_PARAGRAPH 103 | Se toda esta numeração divertida de posições de array está confundindo 104 | você, não tema! Freqüentemente, nós podemos evitá-la completamente 105 | usando vários métodos de array, como este: 106 | END_PARAGRAPH 107 | end 108 | h2 {"O Método #{code 'each'}"} 109 | para do <<-END_PARAGRAPH 110 | #{code 'each'} nos permite fazer algo (o que quer que nós 111 | desejemos) para #{code 'each'} (cada em português) objeto pertencente ao array. Assim, se nós 112 | quiséssemos dizer algo bom sobre cada linguagem no array 113 | abaixo, nós faríamos isto: 114 | END_PARAGRAPH 115 | end 116 | prog do <<-END_CODE 117 | linguagens = ['Português', 'Inglês', 'Ruby'] 118 | 119 | linguagens.each do |ling| 120 | puts 'Eu adoro ' + ling + '!' 121 | puts 'Você não?' 122 | end 123 | 124 | puts 'E vamos ouví-lo sobre C++!' 125 | puts '...' 126 | END_CODE 127 | end 128 | para do <<-END_PARAGRAPH 129 | Então, o que aconteceu? Bem, nós fomos capazes de passar por 130 | todos os objetos no array sem usar nenhum número, e 131 | isto é muito bom. Traduzindo para o português, o programa 132 | acima seria algo como: Para #{code 'cada'} objeto 133 | em #{code 'linguagens'}, aponte a variável #{code 'ling'} 134 | para o objeto e então #{code 'faça'} (do em inglês) tudo que eu disser, 135 | até que você chegue ao #{code 'fim'} (end em inglês). (Como você sabe, 136 | C++ é uma outra linguagem de programação. É muito mais difícil de aprender 137 | do que Ruby; normalmente, um programa C++ será muitas vezes 138 | maior do que um programa Ruby que faz a mesma coisa.) 139 | END_PARAGRAPH 140 | end 141 | para do <<-END_PARAGRAPH 142 | Vocês poderiam estar pensando consigo mesmos, "Isto é muito parecido 143 | com os laços de repetição (loops) que nós aprendemos anteriormente." Sim, é similar. 144 | Uma diferença importante é que o método #{code 'each'} 145 | é apenas: um método. #{code 'while'} e #{code 'end'} 146 | (como #{code 'do'}, #{code 'if'}, #{code 'else'}, e todas as outras palavras em 147 | #{KEYWORD_COLOR}) 148 | não são métodos. Elas são parte fundamental da linguagem 149 | Ruby, como #{code '='} e os parênteses; como os sinais 150 | de pontuações no português. 151 | END_PARAGRAPH 152 | end 153 | para do <<-END_PARAGRAPH 154 | Mas não #{code 'each'}; #{code 'each'} é um apenas um outro 155 | método do array. Métodos como #{code 'each'} que "atuam como" 156 | loops são freqüentemente chamados iteradores. 157 | END_PARAGRAPH 158 | end 159 | para do <<-END_PARAGRAPH 160 | Uma coisa para notar sobre iteradores é que eles são 161 | sempre seguidos por #{code 'do'}...#{code 'end'}. 162 | #{code 'while'} e #{code 'if'} nunca têm um #{code 'do'} 163 | perto deles; nós apenas usamos #{code 'do'} com iteradores. 164 | END_PARAGRAPH 165 | end 166 | para do <<-END_PARAGRAPH 167 | Aqui está um outro atraente iteradorzinho, mas não é um 168 | método de array... é um método de inteiros! 169 | END_PARAGRAPH 170 | end 171 | prog do <<-END_CODE 172 | 3.times do 173 | puts 'Hip-Hip-Urra!' 174 | end 175 | END_CODE 176 | end 177 | h2 {'Mais Métodos de Array'} 178 | para do <<-END_PARAGRAPH 179 | Então nós aprendemos #{code 'each'}, 180 | mas existem muitos outros métodos de array... quase tantos 181 | quantos existem métodos de string! Na verdade, alguns 182 | deles (como #{code 'length'}, #{code 'reverse'}, 183 | #{code '+'}, e #{code '*'}) 184 | funcionam da mesma forma que funcionam para strings, exceto que eles 185 | operam em posições de array ao invés de em 186 | letras de string. Outros, como #{code 'last'} 187 | e #{code 'join'}, são específicos para arrays. Ainda 188 | outros, como #{code 'push'} e #{code 'pop'}, 189 | na verdade modificam o array. E assim como com 190 | os métodos de string, você não tem que se lembrar de 191 | todos estes, desde que você possa se lembrar onde 192 | achar informações sobre eles (bem aqui). 193 | END_PARAGRAPH 194 | end 195 | para do <<-END_PARAGRAPH 196 | Primeiro, vamos dar uma olhada em #{code 'to_s'} e #{code 'join'}. 197 | #{code 'join'} funciona de forma semelhante a #{code 'to_s'}, exceto 198 | que ele adiciona uma string entre os objetos do array. 199 | Vamos dar uma olhada: 200 | END_PARAGRAPH 201 | end 202 | prog do <<-END_CODE 203 | comidas = ['feijoada', 'tapioca', 'bolo de fubá'] 204 | 205 | puts comidas 206 | puts 207 | puts comidas.to_s 208 | puts 209 | puts comidas.join(', ') 210 | puts 211 | puts comidas.join(' :) ') + ' 8)' 212 | 213 | 200.times do 214 | puts [] 215 | end 216 | END_CODE 217 | end 218 | para do <<-END_PARAGRAPH 219 | Como você pode ver, #{code 'puts'} trata os arrays diferentemente 220 | de outros objetos: ele apenas chama #{code 'puts'} em cada um 221 | dos objetos no array. É por isso que chamar #{code 'puts'} para um 222 | um array vazio 200 vezes não faz nada; o array não aponta 223 | para nada, assim não há nada para o #{code 'puts'} mostrar (Fazer 224 | nada 200 vezes ainda é fazer nada). 225 | Tente chamar #{code 'puts'} para um array contendo outros arrays; 226 | fez o que você esperava? 227 | END_PARAGRAPH 228 | end 229 | para do <<-END_PARAGRAPH 230 | Você também notou que eu deixei uma string vazia quando 231 | eu quis #{code 'mostrar'} uma linha em branco? Isto faz a mesma 232 | coisa. 233 | END_PARAGRAPH 234 | end 235 | para do <<-END_PARAGRAPH 236 | Agora vamos dar uma olhada em #{code 'push'}, #{code 'pop'}, 237 | e #{code 'last'}. Os métodos #{code 'push'} e #{code 'pop'} 238 | são de alguma forma opostos, 239 | assim como #{code '+'} e #{code '-'} são. #{code 'push'} adiciona 240 | um objeto no fim do seu array, e #{code 'pop'} 241 | remove o último objeto do array (e diz para você 242 | qual era este objeto). #{code 'last'} é similar a #{code 'pop'} 243 | em dizer para você o que está no fim do array, 244 | exceto que o #{code 'last'} deixa o array em paz. 245 | Novamente, #{code 'push'} e #{code 'pop'} realmente 246 | modificam o array: 247 | END_PARAGRAPH 248 | end 249 | prog do <<-END_CODE 250 | favoritos = [] 251 | favoritos.push 'azul e branco' 252 | favoritos.push 'verde e amarelo' 253 | 254 | puts favoritos[0] 255 | puts favoritos.last 256 | puts favoritos.length 257 | 258 | puts favoritos.pop 259 | puts favoritos 260 | puts favoritos.length 261 | END_CODE 262 | end 263 | h2 {'Algumas Coisas para Tentar'} 264 | para do <<-END_PARAGRAPH 265 | • Escreva o programa que nós comentamos no início 266 | deste capítulo.
267 | Dica: Existe um adorável 268 | método de array que dará a você uma versão ordenada de um 269 | array: #{code 'sort'}. Use-o! 270 | END_PARAGRAPH 271 | end 272 | para do <<-END_PARAGRAPH 273 | • Tente escrever o programa acima sem usar 274 | o método #{code 'sort'}. Uma grande parte da programação é 275 | resolver problemas, assim pratique o máximo que você puder! 276 | END_PARAGRAPH 277 | end 278 | para do <<-END_PARAGRAPH 279 | • Re-escreva seu programa de Tabela de Conteúdos (do capítulo 280 | #{makeLink 'métodos', :generateMethods}). Inicie o programa 281 | com um array que mantém todas as informações sobre sua Tabela 282 | de Conteúdos (nomes de capítulos, números de páginas, etc.). Então imprima 283 | na tela a informação do array em uma Tabela de Conteúdos, 284 | formatada de forma bem bonita. 285 | END_PARAGRAPH 286 | end 287 | para do <<-END_PARAGRAPH 288 | Até o momento aprendemos bastante sobre um número de métodos diferentes. 289 | Agora é hora de aprender como 290 | #{makeLink 'fazer seus próprios métodos', :generateDefMethod}. 291 | END_PARAGRAPH 292 | end 293 | end 294 | end 295 | -------------------------------------------------------------------------------- /lib/learn_to_program_tutorial/beyond.rb: -------------------------------------------------------------------------------- 1 | module Beyond 2 | # 3 | # BEYOND THIS TUTORIAL 4 | # 5 | 6 | def generateBeyond 7 | para do <<-END_PARAGRAPH 8 | Então, onde é que podemos ir agora? Se você tiver uma pergunta, 9 | para quem pode perguntar? 10 | E se você quer que seu programa abra uma página da Web, envie um e-mail, 11 | ou redimensione uma foto digital? 12 | Pois bem, há muitos, muitos lugares onde encontrar ajuda para Ruby. 13 | Infelizmente, essa resposta não tem muita utilidade, não é? :-) 14 | END_PARAGRAPH 15 | end 16 | para do <<-END_PARAGRAPH 17 | Para mim, realmente existem apenas três lugares onde procuro para ajuda 18 | para o Ruby. 19 | Se for uma pequena questão e eu acho que posso experimentar sozinho para 20 | encontrar a resposta, uso irb. 21 | Se for uma questão maior, procuro no meu Pickaxe. 22 | E se simplesmente não consigo dar conta do recado, então peço ajuda na 23 | lista ruby-talk. 24 | END_PARAGRAPH 25 | end 26 | h2 {'IRB: Ruby interativo'} 27 | para do <<-END_PARAGRAPH 28 | Se você instalou Ruby, então você instalou irb. Para usá-lo, basta ir 29 | ao seu prompt de comando e digitar #{input 'irb'}. 30 | Quando você estiver em irb, você pode digitar qualquer expressão ruby 31 | que você queira, e ele devolverá o valor da mesma. 32 | Digite #{input '1 + 2'}, e devolverá #{output '3'}. 33 | (Note que você não precisa usar #{code 'puts'}). 34 | É como uma espécie de calculadora Ruby gigante. Quando tiver concluído, 35 | digite simplesmente #{input 'exit'}. 36 | END_PARAGRAPH 37 | end 38 | para do <<-END_PARAGRAPH 39 | Há muito mais do que isso a respeito do irb, mas você pode aprender 40 | tudo sobre ele no Pickaxe. 41 | END_PARAGRAPH 42 | end 43 | h2 {'O Pickaxe: "Programming Ruby"'} 44 | para do <<-END_PARAGRAPH 45 | O livro sobre Ruby que você não pode perder de jeito nenhum é 46 | "Programming Ruby, The Pragmatic Programmer's Guide", 47 | de Andrew Hunt e David Thomas (os Programadores Pragmáticos). 48 | Embora eu recomende fortemente a 49 | 2ª edição 50 | deste livro excelente, com a cobertura de todas as últimas novidades do Ruby, 51 | você também pode obter uma versão on-line grátis de pouco mais antiga (mas ainda relevante). 52 | (Na verdade, se você instalou a versão do Ruby para Windows, você já tem ela). 53 | END_PARAGRAPH 54 | end 55 | para do <<-END_PARAGRAPH 56 | Você pode encontrar praticamente tudo sobre Ruby, do básico ao avançado, 57 | neste livro. É fácil de ler; é abrangente; é quase perfeito. Eu gostaria 58 | que todas as linguagens (de programação) tivessem um livro desse nível. 59 | Na parte final do livro, você encontrará uma enorme seção detalhando 60 | cada método de cada classe, explicando-o e dando exemplos. 61 | Eu simplesmente amo este livro! 62 | END_PARAGRAPH 63 | end 64 | para do <<-END_PARAGRAPH 65 | Há um sem número de lugares onde você pode obtê-lo (incluindo o próprio 66 | site do Pragmatic Programmers), mas o meu lugar favorito é no 67 | ruby-doc.org. 68 | Esta versão tem um bom índice , bem como um índice remessivo 69 | (no ruby-doc.org tem muitas outras ótimas documentações, tais como a 70 | API Central (Core API) e a Biblioteca Padrão (Standard Library)... 71 | Basicamente, isso documenta tudo que vem com o Ruby. 72 | Verifique.). 73 | END_PARAGRAPH 74 | end 75 | para do <<-END_PARAGRAPH 76 | E por que é chamado de "o Pickaxe" (picareta)? 77 | Pois bem, há uma imagem de uma picareta na capa do livro. 78 | É um nome bobo, eu acho, mas pegou. 79 | END_PARAGRAPH 80 | end 81 | h2 {'Ruby-Talk: uma lista de discussão sobre Ruby'} 82 | para do <<-END_PARAGRAPH 83 | Mesmo com o irb e o Pickaxe, às vezes você ainda pode não dar conta sozinho. 84 | Ou talvez você queira saber se alguém já fez o que você está fazendo, 85 | para ver se você pode utilizá-lo. 86 | Nestes casos, o melhor lugar é ruby-talk, a lista de discussão do Ruby. 87 | É cheia de gente amigável, inteligente, colaborativa. 88 | Para saber mais sobre ela, ou para se inscrever, procure 89 | aqui. 90 | END_PARAGRAPH 91 | end 92 | para do <<-END_PARAGRAPH 93 | ATENÇÃO: Existe um grande número de e-mails 94 | na lista todos os dias. Eu criei uma regra no meu cliente de e-mail 95 | para que não fique tudo na mesma pasta. Mas se você não quiser ter 96 | que fazer isso, você não precisa! 97 | A lista de discussão ruby-talk tem um espelho no grupo de notícias 98 | comp.lang.ruby, assim, você pode ver as mensagens por lá. Em suma, 99 | você verá as mesmas mensagens, mas de uma maneira um pouco diferente. 100 | END_PARAGRAPH 101 | end 102 | h2 {'Tim Toady'} 103 | para do <<-END_PARAGRAPH 104 | Tenho tentado proteger você de algo com o que vai esbarrar em breve, 105 | é o conceito de TMTOWTDI (pronunciado como "Tim Toady"): There's More 106 | Than One Way To Do It (Há Mais De Uma Maneira Para Fazer Isso). 107 | END_PARAGRAPH 108 | end 109 | para do <<-END_PARAGRAPH 110 | Agora alguns vão lhe dizer que TMTOWTDI é uma coisa maravilhosa, 111 | enquanto outros se sentem bastante diferente. 112 | Eu realmente não tenho fortes sentimentos sobre o assunto em geral, 113 | mas eu acho que é uma péssima maneira de ensinar para alguém como programar. 114 | (Como se aprender uma maneira de fazer alguma coisa não fosse 115 | suficientemente desafiante e confuso!). 116 | END_PARAGRAPH 117 | end 118 | para do <<-END_PARAGRAPH 119 | No entanto, agora que você está indo além deste tutorial, você verá 120 | muito código diversificado. Por exemplo, posso pensar em pelo menos 121 | cinco outras maneiras de criar uma string (além de circundar algum 122 | texto com aspas simples), e cada um deles funciona de maneira um pouco 123 | diferente. Eu só lhe mostrei o mais simples dos seis. 124 | END_PARAGRAPH 125 | end 126 | para do <<-END_PARAGRAPH 127 | E quando conversamos sobre ramificações, mostrei para você 128 | #{code 'if'}, mas não lhe mostrei #{code 'unless'}. 129 | Eu vou deixá-lo entender isso no irb. 130 | END_PARAGRAPH 131 | end 132 | para do <<-END_PARAGRAPH 133 | Outro agradável atalho que você pode usar com #{code 'if'}, 134 | #{code 'unless'}, #{code 'while'}, é a elegante versão de uma linha: 135 | END_PARAGRAPH 136 | end 137 | prog do <<-END_CODE 138 | # Estas palavras são de um programa que escrevi para gerar 139 | # baboseiras em inglês. Bacana, não? 140 | puts 'grobably combergearl kitatently thememberate' if 5 == 2**2 + 1**1 141 | puts 'enlestrationshifter supposine follutify blace' unless 'Chris'.length == 5 142 | END_CODE 143 | end 144 | para do <<-END_PARAGRAPH 145 | E, finalmente, há uma outra forma de escrever métodos que recebem blocos 146 | (não procs). Vimos isso onde recebemos o bloco e o transformamos em uma 147 | proc usando o truque do #{code '&block'} na lista de parâmetros quando 148 | se define a função. Depois, para chamar o bloco, você usa 149 | #{code 'block.call'}. Pois bem, há um caminho mais curto (embora 150 | pessoalmente eu o julgue mais confuso). Em vez disto: 151 | END_PARAGRAPH 152 | end 153 | prog do <<-END_CODE 154 | def facaDuasVezes(&bloco) 155 | bloco.call 156 | bloco.call 157 | end 158 | 159 | facaDuasVezes do 160 | puts 'murditivent flavitemphan siresent litics' 161 | end 162 | END_CODE 163 | end 164 | para do <<-END_PARAGRAPH 165 | ...você faz isso: 166 | END_PARAGRAPH 167 | end 168 | prog do <<-END_CODE 169 | def facaDuasVezes 170 | yield 171 | yield 172 | end 173 | 174 | facaDuasVezes do 175 | puts 'buritiate mustripe lablic acticise' 176 | end 177 | END_CODE 178 | end 179 | para do <<-END_PARAGRAPH 180 | Não sei ... O que você acha? Talvez seja eu, mas... #{code 'yield'}?! 181 | Se fosse algo como #{code 'chame_o_bloco_escondido'} (#{code 'call_the_hidden_block'}) 182 | ou algo assim, faria muito mais sentido para mim. Muitas pessoas dizem que 183 | #{code 'yield'} faz sentido para elas. Mas acho que esse é o propósito de 184 | TMTOWTDI: elas fazem do jeito delas, e eu vou fazer à minha maneira. 185 | END_PARAGRAPH 186 | end 187 | h2 {'O FIM'} 188 | para do <<-END_PARAGRAPH 189 | Use-o para o bem e não para o mal. :-) E se você achou este tutorial útil 190 | (ou confuso, ou se você encontrou um erro), 191 | me faça saber! 192 | END_PARAGRAPH 193 | end 194 | 195 | end 196 | end 197 | -------------------------------------------------------------------------------- /lib/learn_to_program_tutorial/blocks_procs.rb: -------------------------------------------------------------------------------- 1 | module BlocksProcs 2 | # 3 | # BLOCKS AND PROCS 4 | # 5 | 6 | def generateBlocksProcs 7 | para do <<-END_PARAGRAPH 8 | Este é, definitivamente, um dos recursos mais legais de Ruby. Algumas 9 | outras linguagens têm esse recurso, porém elas podem chamar isso 10 | de formas diferentes (como closures), mas muitas 11 | das mais populares não, o que é uma pena. 12 | END_PARAGRAPH 13 | end 14 | para do <<-END_PARAGRAPH 15 | Então o que é essa nova coisa legal? É a habilidade de pegar 16 | um bloco de código (código entre #{code 'do'} 17 | e #{code 'end'}), amarrar tudo em um objeto (chamado de 18 | proc), armazenar isso em uma variável e passar isso 19 | para um método, e rodar o código do bloco quando você quiser 20 | (mais de uma vez, se você quiser). Então, é como se fosse um método, 21 | exceto pelo fato de que isso não está em um objeto (isso é um objeto), 22 | e você pode armazená-lo ou passá-lo adiante, como com qualquer outro objeto. 23 | Acho que é hora de um exemplo: 24 | END_PARAGRAPH 25 | end 26 | prog do <<-END_CODE 27 | saudacao = Proc.new do 28 | puts 'Olá!' 29 | end 30 | 31 | saudacao.call 32 | saudacao.call 33 | saudacao.call 34 | END_CODE 35 | end 36 | para do <<-END_PARAGRAPH 37 | Eu criei uma proc (eu acho que é abreviatura para "procedimento", 38 | mas o que importa é que rima com "block") que tem um bloco de código, então 39 | eu chamei (#{code 'call'}) a proc três vezes. 40 | Como você pode ver, parece, em muito, com um método. 41 | END_PARAGRAPH 42 | end 43 | para do <<-END_PARAGRAPH 44 | Atualmente, é muito mais parecido com um método do que eu mostrei para você, 45 | porque blocos podem receber parâmetros: 46 | END_PARAGRAPH 47 | end 48 | prog do <<-END_CODE 49 | VoceGostade = Proc.new do |umaBoaCoisa| 50 | puts 'Eu *realmente* gosto de '+umaBoaCoisa+'!' 51 | end 52 | 53 | VoceGostade.call 'chocolate' 54 | VoceGostade.call 'ruby' 55 | END_CODE 56 | end 57 | para do <<-END_PARAGRAPH 58 | Certo, então nós vimos o que blocos e procs são e como os usar, mas e daí? 59 | Por que não usar apenas métodos? Bem, isso é porque existem algumas coisas 60 | que você não pode fazer com métodos. Particularmente, você não pode passar 61 | métodos para outros métodos (mas você pode passar procs para métodos), e 62 | métodos não podem retornar outros métodos (mas podem retornar procs). É apenas 63 | por isso que procs são objetos; métodos não. 64 | END_PARAGRAPH 65 | end 66 | para do <<-END_PARAGRAPH 67 | (De qualquer forma, isso parece familiar? Sim, você já viu blocos antes... quando 68 | você aprendeu sobre iteradores. Mas vamos voltar a falar disso daqui a pouco.) 69 | END_PARAGRAPH 70 | end 71 | h2 { 'Métodos que Recebem Procs' } 72 | para do <<-END_PARAGRAPH 73 | Quando passamos uma proc em um método, nós podemos controlar como, se ou quantas vezes 74 | nós vamos chamar a proc. Por exemplo, posso dizer que há uma coisa que nós queremos 75 | fazer antes e depois que um código é executado: 76 | END_PARAGRAPH 77 | end 78 | prog do <<-END_CODE 79 | def FacaUmaCoisaImportante umaProc 80 | puts 'Todo mundo apenas ESPERE! Eu tenho uma coisa a fazer...' 81 | umaProc.call 82 | puts 'Certo pessoal, Eu terminei. Voltem a fazer o que estavam fazendo.' 83 | end 84 | 85 | digaOla = Proc.new do 86 | puts 'olá' 87 | end 88 | 89 | digaTchau = Proc.new do 90 | puts 'tchau' 91 | end 92 | 93 | FacaUmaCoisaImportante digaOla 94 | FacaUmaCoisaImportante digaTchau 95 | END_CODE 96 | end 97 | para do <<-END_PARAGRAPH 98 | Talvez isso não pareça tão fabuloso... mas é. :-) 99 | É muito comum em programação que alguns requesitos críticos sejam executados. 100 | Se você grava um arquivo, por exemplo, você deve abrir o arquivo, escrever 101 | o que quiser lá dentro e então fechar o arquivo. Se você se esquecer de fechar o arquivo, 102 | Coisas Ruins(tm) podem acontecer. Mas toda a vez que você quiser salvar ou carregar um arquivo, 103 | você deve fazer a mesma coisa: abrir o arquivo, fazer o que você realmente quiser com ele 104 | e então fechar o arquivo. Isso é entediante e fácil de esquecer. Em Ruby, salvar (ou carregar) 105 | arquivos funciona similarmente com o código anterior, então você não precisa se preocupar 106 | com nada além de o que você quer salvar (ou carregar) (No próximo capítulo eu vou lhe 107 | mostrar como fazer coisas como salvar e carregar arquivos). 108 | END_PARAGRAPH 109 | end 110 | para do <<-END_PARAGRAPH 111 | Você pode também escrever métodos que vão determinar quantas vezes, ou mesmo 112 | se uma proc será chamada. Aqui está um método que irá chamar uma proc 113 | metade do tempo, e outra que irá chamar a proc duas vezes. 114 | END_PARAGRAPH 115 | end 116 | prog do <<-END_CODE 117 | def talvezFaca umaProc 118 | if rand(2) == 0 119 | umaProc.call 120 | end 121 | end 122 | 123 | def FacaDuasVezes umaProc 124 | umaProc.call 125 | umaProc.call 126 | end 127 | 128 | piscar = Proc.new do 129 | puts '' 130 | end 131 | 132 | olhandofixamente = Proc.new do 133 | puts '' 134 | end 135 | 136 | talvezFaca piscar 137 | talvezFaca olhandofixamente 138 | FacaDuasVezes piscar 139 | FacaDuasVezes olhandofixamente 140 | END_CODE 141 | end 142 | para do <<-END_PARAGRAPH 143 | (Se você recarregar essa página algumas vezes, você verá que a saída muda) 144 | Esses são alguns dos usos mais comuns de procs, que nos possibilita fazer coisas que nós 145 | simplesmente não poderíamos fazer usando apenas métodos. Claro, você pode escrever um método 146 | que "pisque" duas vezes, mas você não pode escrever um que apenas faça qualquer coisa duas vezes! 147 | END_PARAGRAPH 148 | end 149 | para do <<-END_PARAGRAPH 150 | Antes de seguirmos adiante, vamos olhar um último exemplo. Até agora, 151 | as procs que nós usamos foram muito similares umas às outras. Agora, 152 | elas serão um pouco diferentes, assim você poderá ver como um método 153 | depende das procs que lhe são passadas. Nosso método irá receber 154 | um objeto e uma proc e irá chamar essa proc naquele objeto. Se a 155 | proc retornar falso, nós saímos; caso contrário, nós chamamos a proc 156 | com o objeto retornado. Nós vamos continuar fazendo isso até que a proc 157 | retorne falso (o que é o melhor a fazer eventualmente, ou o programá irá 158 | travar). O método irá retornar o último valor não falso retornado pela proc. 159 | END_PARAGRAPH 160 | end 161 | prog do <<-END_CODE 162 | def facaAteFalso primeiraEntrada, umaProc 163 | entrada = primeiraEntrada 164 | saida = primeiraEntrada 165 | 166 | while saida 167 | entrada = saida 168 | saida = umaProc.call entrada 169 | end 170 | 171 | entrada 172 | end 173 | 174 | construindoVetorDeQuadrados = Proc.new do |vetor| 175 | ultimoNumero = vetor.last 176 | if ultimoNumero <= 0 177 | false 178 | else 179 | vetor.pop # Jogue fora o último número... 180 | vetor.push ultimoNumero*ultimoNumero # ... e o substitua com esse quadrado... 181 | vetor.push ultimoNumero-1 # ... seguido pelo número imediatamente anterior. 182 | end 183 | end 184 | 185 | sempreFalso = Proc.new do |apenasIgnoreme| 186 | false 187 | end 188 | 189 | puts facaAteFalso([5], construindoVetorDeQuadrados).inspect 190 | puts facaAteFalso('Estou escrevendo isso às 3:00; alguém me derrube!', sempreFalso) 191 | END_CODE 192 | end 193 | para do <<-END_PARAGRAPH 194 | Certo, esse foi um exemplo estranho, eu admito. Mas isso mostra como nosso método 195 | age diferentemente quando recebe diferentes procs. 196 | END_PARAGRAPH 197 | end 198 | para do <<-END_PARAGRAPH 199 | O método #{code 'inspect'} é muito parecido com o #{code 'to_s'}, exceto 200 | pelo fato de que a string retornada tenta mostrar para você o código em ruby 201 | que está construindo o objeto que você passou. Aqui ele nos mostra todo o vetor 202 | retornado pela nossa primeira chamada a #{code 'facaAteFalso'}. Você também deve 203 | ter notado que nós nunca elevamos aquele #{code '0'} ao quadrado, no fim do vetor. Já que 204 | #{code '0'} elevado ao quadrado continua apenas #{code '0'}, nós não precisamos fazer isso. 205 | E já que #{code 'sempreFalso'} foi, você sabe, sempre #{code 'falso'}, 206 | #{code 'facaAteFalso'} não fez nada na segunda vez que a chamamos; apenas retornou o que 207 | lhe foi passada. 208 | END_PARAGRAPH 209 | end 210 | h2 { 'Métodos que Retornam Procs' } 211 | para do <<-END_PARAGRAPH 212 | Uma das outras coisas legais que você pode fazer com procs é 213 | criá-las em métodos e retorná-las. Isso permite toda uma variedade 214 | de poderes de programação malucos (coisas com nomes impressionantes, 215 | como avaliação preguiçosa, estrutura de dados infinita, 216 | e temperando com curry), mas o fato é de que eu nunca faço isso 217 | na prática e eu não me lembro de ter visto ninguém fazendo isso. Eu acho 218 | que isso é o tipo de coisa que você acaba não fazendo em Ruby, ou talvez 219 | Ruby apenas encoraje-o a achar outras soluções: eu não sei. De qualquer forma, 220 | eu vou tocar no assunto apenas brevemente. 221 | END_PARAGRAPH 222 | end 223 | para do <<-END_PARAGRAPH 224 | Nesse exemplo, #{code 'compor'} recebe duas procs e retorna uma nova proc 225 | que, quando chamada, chama uma terceira proc e passa seu resultado 226 | para a segunda proc. 227 | END_PARAGRAPH 228 | end 229 | prog do <<-END_CODE 230 | def compor proc1, proc2 231 | Proc.new do |x| 232 | proc2.call(proc1.call(x)) 233 | end 234 | end 235 | 236 | quadrado = Proc.new do |x| 237 | x * x 238 | end 239 | 240 | dobre = Proc.new do |x| 241 | x + x 242 | end 243 | 244 | dobreeEleve = compor dobre, quadrado 245 | eleveeDobre = compor quadrado, dobre 246 | 247 | puts dobreeEleve.call(5) 248 | puts eleveeDobre.call(5) 249 | END_CODE 250 | end 251 | para do <<-END_PARAGRAPH 252 | Note que a chamada para #{code 'proc1'} deve ser inserida 253 | entre parenteses dentro de #{code 'proc2'}, para que seja executada primeiro. 254 | END_PARAGRAPH 255 | end 256 | h2 { 'Passando Blocos (E Não Procs) para Métodos' } 257 | para do <<-END_PARAGRAPH 258 | Certo, isso foi muito interessante academicamente, mas de pouca 259 | utilidade prática. Uma porção desse problema é que há três passos 260 | que você deve seguir (definir o método, construir a proc e chamar 261 | o método com a proc), quando eles podem ser resumidos em apenas 262 | dois (definir o método e passar o bloco diretamente ao método, 263 | sem usar uma proc), uma vez que na maior parte das vezes você não 264 | vai querer usar a proc ou o bloco depois que o passar para um método. 265 | Bem, você não sabe, mas Ruby tem isso para nós! Na verdade, 266 | você já estava fazendo isso todas as vezes que usou iteradores. 267 | END_PARAGRAPH 268 | end 269 | para do <<-END_PARAGRAPH 270 | Eu vou mostrar a você um exemplo rápido, então nós vamos falar sobre isso. 271 | END_PARAGRAPH 272 | end 273 | # HACK ALERT!!! (Eu não posso chegar a um namespace global transparentemente 274 | # de dentro do objeto StringIO em um script mod_ruby.) 275 | arrayClassHack = <<-END_CODE 276 | def cadaComparacao(&eraUmBloco_agoraUmaProc) 277 | eIgual = true # Nós começamos com "verdadeiro" porque vetores começam com 0, mesmo se iguais. 278 | 279 | self.each do |objeto| 280 | if eIgual 281 | eraUmBloco_agoraUmaProc.call objeto 282 | end 283 | 284 | eIgual = (not eIgual) # Comutando entre igual para diferente, ou de diferente para igual. 285 | end 286 | end 287 | END_CODE 288 | 289 | Array.module_eval arrayClassHack # Esta é a definição real do método. 290 | # A seguir é definido um método em "outra" classe de inteiros: 291 | # FIM HACK ALERT!!! 292 | prog do <<-END_CODE 293 | class Array 294 | 295 | #{arrayClassHack} 296 | end 297 | 298 | ['maçã', 'maçã podre', 'cereja', 'mamona'].cadaComparacao do |fruta| 299 | puts 'Hum! Eu adoro tortas de '+fruta+', você não?' 300 | end 301 | 302 | # Lembre-se, nós estamos pegando os mesmos elementos numerados 303 | # do array, todos que se relacionam com os outros números, 304 | # apenas porque gosto de causar esse tipo de problema. 305 | [1, 2, 3, 4, 5].cadaComparacao do |bola_estranha| 306 | puts bola_estranha.to_s+' não é um número!' 307 | end 308 | END_CODE 309 | end 310 | para do <<-END_PARAGRAPH 311 | Para passar um bloco para #{code 'cadaComparacao'}, tudo o que temos que fazer 312 | é anexar o bloco após o método. Você pode passar um bloco para qualquer método 313 | dessa maneira, apesar de que muitos métodos vão apenas ignorar o bloco. Para 314 | fazer seu método não ignorar o bloco, mas pegá-lo e transformá-lo em 315 | uma proc, ponha o nome da proc no começo da lista dos parâmetros do seu método, 316 | precedido por um 'e' comercial (#{code '&'}). Essa parte é um pequeno truque, 317 | mas não é tão ruim, e você apenas precisa fazer isso uma vez (quando você 318 | define o método). Então você pode usar o método de novo, e de novo e de novo, 319 | assim como os métodos da linguagem que aceitam blocos, como o #{code 'each'} 320 | e o #{code 'times'} (Lembra-se do #{code '5.times do'}...?). 321 | END_PARAGRAPH 322 | end 323 | para do <<-END_PARAGRAPH 324 | Se você estiver confuso, apenas lembre-se do que supostamente o método 325 | #{code 'cadaComparacao'} faz: chama o bloco passado como parâmetro para 326 | cada elemento no vetor. Depois que você o escrever e ele estiver funcionando, 327 | você não vai precisar pensar sobre o que está acontecendo realmente por baixo 328 | dos panos ("qual bloco é chamado quando??"); na verdade, é exatamente por isso 329 | que escrevemos métodos assim: nós nunca mais vamos precisar pensar sobre 330 | como eles funcionam novamente. Nós vamos apenas usar-los. 331 | END_PARAGRAPH 332 | end 333 | para do <<-END_PARAGRAPH 334 | Eu lembro que uma vez eu quis cronometrar quanto tempo cada 335 | seção do meu código estava demorando (Isso é algo conhecido como 336 | sumarizar o código). Então, eu escrevi um método que 337 | pegava o tempo antes de executar o código, o executava e então 338 | fazia uma nova medição do tempo e me retornava a diferença. Eu 339 | não estou conseguindo achar o código agora, mas eu não preciso disso: 340 | provavelmente é um código parecido com esse: 341 | END_PARAGRAPH 342 | end 343 | prog do <<-END_CODE 344 | def sumario descricaoDoBloco, &bloco 345 | tempoInicial = Time.now 346 | 347 | bloco.call 348 | 349 | duracao = Time.now - tempoInicial 350 | 351 | puts descricaoDoBloco+': '+duracao.to_s+' segundos' 352 | end 353 | 354 | sumario 'dobrando 25000 vezes' do 355 | numero = 1 356 | 357 | 25000.times do 358 | numero = numero + numero 359 | end 360 | 361 | puts numero.to_s.length.to_s+' dígitos' # É isso mesmo: o número de dígitos nesse número ENORME. 362 | end 363 | 364 | sumario 'contando até um milhão' do 365 | numero = 0 366 | 367 | 1000000.times do 368 | numero = numero + 1 369 | end 370 | end 371 | END_CODE 372 | end 373 | para do <<-END_PARAGRAPH 374 | Que simplicidade! Que elegância! Com aquele pequeno método 375 | eu posso, agora, facilmente cronometrar qualquer seção, de qualquer 376 | programa, que eu queira, eu apenas preciso jogar o código para um bloco 377 | e enviar ele para o #{code 'sumario'}. 378 | O que poderia ser mais simples? Em muitas linguagens, eu teria que 379 | adicionar explicitamente o código de cronometragem (tudo o que está 380 | em #{code 'sumario'}) em volta de qualquer seção que eu queira medir. 381 | Em Ruby, porém, eu deixo tudo em um só lugar, e (o mais importante) 382 | fora do meu caminho! 383 | END_PARAGRAPH 384 | end 385 | h2 {'Algumas Coisinhas Para Tentar'} 386 | para do <<-END_PARAGRAPH 387 | • Relógio Cuco. Escreva um método que pegue um bloco 388 | e o chame de hora em hora. Assim, se eu passar o bloco #{code "do puts 'DONG!' end"}, 389 | ele deve tocar como um relógio cuco. Teste seu método com diferentes 390 | blocos (inclusive o que eu mostrei para você). 391 | Dica: Você pode usar 392 | #{code 'Time.now.hour'} para pegar a hora atual. 393 | Porém, isso retorna um número entre #{code '0'} e #{code '23'}, 394 | então você deve alterar esses números para os números de um relógio normal, entre 395 | (#{code '1'} e #{code '12'}). 396 | END_PARAGRAPH 397 | end 398 | para do <<-END_PARAGRAPH 399 | • Logger do programa. Escreva um método chamado #{code 'log'}, que 400 | pegue uma string como descrição de um bloco e, é claro, um bloco. Similarmente ao 401 | #{code 'FacaUmaCoisaImportante'}, essa deve retornar (#{code 'puts'}) uma string 402 | dizendo que o bloco foi iniciado e outra string ao fim, dizendo que é o fim da 403 | execução do bloco, e também dizendo o que o bloco retornou. Teste seu método 404 | enviando um bloco de código. Dentro do bloco, coloque outra chamada para 405 | #{code 'log'}, passando outro bloco para o mesmo (isto é chamado de nesting). 406 | Em outras palavras, sua saída deve se parecer com isso: 407 | END_PARAGRAPH 408 | end 409 | puts '
' +
410 |             'Começando "bloco externo"...' + $/ +
411 |             'Começando "um bloco um pouco menor"...' + $/ +
412 |             '..."um bloco um pouco menor" terminou retornando:  5' + $/ +
413 |             'Começando "um outro bloco"...' + $/ +
414 |             '..."um outro bloco" terminou retornando: Eu gosto de comida tailandesa!' + $/ +
415 |             '..."bloco externo" terminou retornando: false' + $/ +
416 |             '
' 417 | para do <<-END_PARAGRAPH 418 | • Um Logger aperfeiçoado. A saída do último logger é muito difícil de 419 | ler, e fica muito pior a medida que você for usando. Seria muito mais fácil de ler 420 | se você identasse as linhas para os blocos internos. Para fazer isso, você vai precisar 421 | saber quão profundamente aninhado você está toda vez que for escrever algo no log. Para 422 | fazer isso, use uma variável global, uma variável que você possa ver de 423 | qualquer lugar de seu código. Para instânciar uma variável global, você deve 424 | precedê-la com um #{code '$'}, assim: #{code '$global'}, #{code '$nestingDepth'}, 425 | e #{code '$bigTopPeeWee'}. 426 | Enfim, seu logger deve ter uma saída parecida com essa: 427 | END_PARAGRAPH 428 | end 429 | puts '
' +
430 |             'Começando "bloco externo"...' + $/ +
431 |             '  Começando "um pequeno bloco"...' + $/ +
432 |             '    Começando "pequenino bloco"...' + $/ +
433 |             '    ..."pequenino bloco" terminou retornando: muito amor' + $/ +
434 |             '  ..."um pequeno bloco" terminou retornando: 42' + $/ +
435 |             '  Começando "um outro bloco"...' + $/ +
436 |             '  ..."um outro bloco" terminou retornando: Eu adoro comida indiana!' + $/ +
437 |             '..."bloco externo" terminou retornando: true' + $/ +
438 |             '
' 439 | para do <<-END_PARAGRAPH 440 | Bem, isso é tudo que você aprendeu com esse tutorial. 441 | Parabéns! Você aprendeu muito. Talvez você sinta 442 | como se não lembrasse de nada, ou talvez você tenha 443 | pulado algumas partes... Relaxe. Programação não é o que 444 | você sabe, e sim o que você faz. À medida que você for 445 | aprendendo onde procurar as coisas que você esquecer, 446 | você estará indo bem. Eu espero que você não ache que eu 447 | escrevi tudo isso sem ficar conferindo a cada minuto! 448 | Porque eu fiz isso. Eu também tive muita ajuda com os 449 | códigos que rodam em todos os exemplos desse tutorial. 450 | Mas onde eu estava pesquisando tudo e a quem 451 | eu estava pedindo ajuda? 452 | #{makeLink 'Deixe-me conhecê-lo...', :generateBeyond} 453 | END_PARAGRAPH 454 | end 455 | end 456 | end 457 | -------------------------------------------------------------------------------- /lib/learn_to_program_tutorial/conversion.rb: -------------------------------------------------------------------------------- 1 | module Conversion 2 | # 3 | # CONVERSION 4 | # 5 | 6 | def generateConversion 7 | para do <<-END_PARAGRAPH 8 | Nós vimos alguns tipos diferentes de objetos 9 | (#{makeLink 'números', :generateNumbers} e #{makeLink 'letras', :generateLetters}), 10 | e nós fizemos #{makeLink 'variáveis', :generateVariables} para apontar para elas; 11 | a coisa que queremos fazer a seguir é fazer com que todas se encaixem. 12 | END_PARAGRAPH 13 | end 14 | para do <<-END_PARAGRAPH 15 | Nós vimos que se desejássemos que um programa imprimisse #{output '25'}, 16 | o código a seguir não funcionaria, porque 17 | você não pode somar números e strings: 18 | END_PARAGRAPH 19 | end 20 | prog false do <<-END_CODE 21 | var1 = 2 22 | var2 = '5' 23 | 24 | puts var1 + var2 25 | END_CODE 26 | end 27 | para do <<-END_PARAGRAPH 28 | Parte do problema é que seu computador não sabe se você está 29 | querendo #{output '7'} (#{code '2 + 5'}) ou #{output '25'} 30 | (#{code "'2' + '5'"}). 31 | END_PARAGRAPH 32 | end 33 | para do <<-END_PARAGRAPH 34 | Antes que possamos somar os dois, precisamos de alguma maneira 35 | de obter a versão em string de #{code 'var1'}, ou então de obter 36 | a versão inteira de #{code 'var2'}. 37 | END_PARAGRAPH 38 | end 39 | h2 {'Conversions'} 40 | para do <<-END_PARAGRAPH 41 | Para obter a versão string de um objeto, simplesmente escrevemos 42 | #{code '.to_s'} depois dele: 43 | END_PARAGRAPH 44 | end 45 | prog do <<-END_CODE 46 | var1 = 2 47 | var2 = '5' 48 | 49 | puts var1.to_s + var2 50 | END_CODE 51 | end 52 | para do <<-END_PARAGRAPH 53 | Similarmente, #{code 'to_i'} fornece a versão inteira de um objeto, 54 | e #{code 'to_f'} dá a versão float. Vejamos o que esses três método 55 | fazem (e não fazem) com mais detalhe: 56 | END_PARAGRAPH 57 | end 58 | prog do <<-END_CODE 59 | var1 = 2 60 | var2 = '5' 61 | 62 | puts var1.to_s + var2 63 | puts var1 + var2.to_i 64 | END_CODE 65 | end 66 | para do <<-END_PARAGRAPH 67 | Note que, mesmo depois que obtivemos a versão string de 68 | #{code 'var1'} por meio de #{code 'to_s'}, #{code 'var1'} 69 | sempre apontou para #{code '2'}, e nunca para #{code "'2'"}. 70 | A não ser que reatribuamos #{code 'var1'} explicitamente (o que 71 | requer um sinal de #{code '='}), ela vai apontar para #{code '2'} 72 | enquanto o programa estiver rodando. 73 | END_PARAGRAPH 74 | end 75 | para do <<-END_PARAGRAPH 76 | Agora vamos tentar algumas conversões mais interessantes (e alguma apenas 77 | esquisitas): 78 | END_PARAGRAPH 79 | end 80 | prog do <<-END_CODE 81 | puts '15'.to_f 82 | puts '99.999'.to_f 83 | puts '99.999'.to_i 84 | puts '' 85 | puts '5 é meu número favorito!'.to_i 86 | puts 'Quem foi que te perguntou sobre o 5?'.to_i 87 | puts 'Sua mãe.'.to_f 88 | puts '' 89 | puts 'stringuelingue'.to_s 90 | puts 3.to_i 91 | END_CODE 92 | end 93 | para do <<-END_PARAGRAPH 94 | É provável que tenha havido surpresas. A primeira é bem padrão e 95 | dá #{output '15'}. 96 | Depois disso, convertemos a string #{code "'99.999'"} para um float 97 | e para um inteiro. O float ficou como esperávamos; o inteiro, como 98 | sempre, foi arredondado para baixo. 99 | END_PARAGRAPH 100 | end 101 | para do <<-END_PARAGRAPH 102 | Em seguida temos alguns exemplos de strings... atípicas convertidas 103 | em números. #{code 'to_i'} ignora a primeira coisa que ela não entende, 104 | e o resto da string daquele ponto em diante. Então a primeira string 105 | foi convertida para #{code '5'}, mas as outras, já que começavam com 106 | letras, foram ignoradas por completo... então o computador só escolhe 107 | zero. 108 | END_PARAGRAPH 109 | end 110 | para do <<-END_PARAGRAPH 111 | Por fim, vimos que nossas duas últimas conversas não fizeram nada, 112 | exatamente como esperávamos. 113 | END_PARAGRAPH 114 | end 115 | h2 {'Uma Outra Olhadela em '+(code 'puts')} 116 | para do <<-END_PARAGRAPH 117 | Há alguma coisa estranha no nosso método favorito... Dê uma olhadinha: 118 | END_PARAGRAPH 119 | end 120 | prog do <<-END_CODE 121 | puts 20 122 | puts 20.to_s 123 | puts '20' 124 | END_CODE 125 | end 126 | para do <<-END_PARAGRAPH 127 | Por que é que essas três imprimem a mesma coisa? Tudo bem, as duas 128 | últimas deveriam mesmo, já que #{code '20.to_s'} é 129 | #{code "'20'"}. Mas e a primeira, o inteiro #{code '20'}? Falando nisso, 130 | faz algum sentido escrever o inteiro 20? Quando você escreve 131 | um 2 e depois um 0 num papel, você está escrevendo 132 | uma string, não um inteiro. O inteiro 20 é o número de dedos 133 | que eu possuo, e não um 2 seguido de um 0. 134 | END_PARAGRAPH 135 | end 136 | para do <<-END_PARAGRAPH 137 | O nosso amigo #{code 'puts'} carrega um grande segredo: antes de tentar 138 | escrever um objeto, #{code 'puts'} usa #{code 'to_s'} para obter a 139 | versão string do mesmo. Na verdade, o s em #{code 'puts'} 140 | está lá representando string; #{code 'puts'} na verdade 141 | significa put string (colocar string). 142 | END_PARAGRAPH 143 | end 144 | para do <<-END_PARAGRAPH 145 | Isso pode não parecer muito animador agora, mas há muitos, 146 | muitos tipos de objetos em Ruby (você vai até aprender 147 | a fazer o seu próprio!), e é bom saber o que vai acontecer 148 | se você tentar usar #{code 'puts'} num objeto muito estranho, 149 | como uma foto da sua avó, ou um arquivo de música ou algo assim. 150 | Mas isso vem depois... 151 | END_PARAGRAPH 152 | end 153 | para do <<-END_PARAGRAPH 154 | Até lá, nós temos mais alguns métodos para você, e eles permitem 155 | que escrevamos um bando de programas divertidos... 156 | END_PARAGRAPH 157 | end 158 | h2 {'Os Métodos '+(code 'gets')+' e '+(code 'chomp')} 159 | para do <<-END_PARAGRAPH 160 | Se #{code 'puts'} significa colocar string (N.T.: put significa 161 | "colocar"), acho que você pode adivinhar o que #{code 'gets'} quer dizer 162 | (N.T.: get, em inglês, entre várias acepções, significa pegar, obter). 163 | E assim como #{code 'puts'} sempre cospe strings, #{code 'gets'} vai apenas 164 | obter strings. E de onde ele as pega? 165 | END_PARAGRAPH 166 | end 167 | para do <<-END_PARAGRAPH 168 | De você! Tudo bem, do seu teclado. Já que seu teclado só produz strings, 169 | isso funciona muito bem. O que acontece, na verdade, é que #{code 'gets'} 170 | fica lá esperando, lendo o que você digita até que você pressione 171 | Enter. Vamos experimentar: 172 | END_PARAGRAPH 173 | end 174 | prog ['Tem um eco aqui?'] do <<-END_CODE 175 | puts gets 176 | END_CODE 177 | end 178 | para do <<-END_PARAGRAPH 179 | Claro, tudo que você digitar vai ser repetido para você. Rode 180 | algumas vezes e tente digitar coisas diferentes. 181 | END_PARAGRAPH 182 | end 183 | para do <<-END_PARAGRAPH 184 | Agora podemos fazer programas interativos! Neste, digite 185 | o seu nome para que ele lhe saude: 186 | END_PARAGRAPH 187 | end 188 | prog ['Chris'], 'Eca! Eu acabei de rodá-lo—escrevi meu nome—e aconteceu isto:' do <<-END_CODE 189 | puts 'Olá, qual é o seu nome?' 190 | name = gets 191 | puts 'Seu nome é ' + name + '? Que nome bonito!' 192 | puts 'Prazer em conhecê-lo, ' + name + '. :)' 193 | END_CODE 194 | end 195 | para do <<-END_PARAGRAPH 196 | Hmmm... parece que quando eu digitei as letras C, 197 | h, r, i, s, e pressionei 198 | Enter, #{code 'gets'} obteve todas as letras do meu nome 199 | e o Enter! Felizmente, existe um método exatamente 200 | pra esse tipo de coisa: #{code 'chomp'}. Ele retira qualquer 201 | Enter que esteja lá de bobeira no fim da sua string. Vamos 202 | testar aquele programa de novo, mas com #{code 'chomp'} para ajudar: 203 | END_PARAGRAPH 204 | end 205 | prog ['Chris'] do <<-END_CODE 206 | puts 'Olá, qual é o seu nome?' 207 | name = gets.chomp 208 | puts 'Seu nome é ' + name + '? Que nome bonito!' 209 | puts 'Prazer em conhecê-lo, ' + name + '. :)' 210 | END_CODE 211 | end 212 | para do <<-END_PARAGRAPH 213 | Muito melhor! Perceba que já que #{code 'name'} aponta para 214 | #{code 'gets.chomp'}, não temos que dizer #{code 'name.chomp'}; 215 | #{code 'name'} já foi #{code 'mastiga'}do (N.T.: chomp, em Inglês 216 | é "mastigar"). 217 | END_PARAGRAPH 218 | end 219 | h2 {'Umas Coisinhas Para Tentar'} 220 | para do <<-END_PARAGRAPH 221 | • Escreva um programa que peça o nome de uma pessoa, depois 222 | o sobrenome. Por fim, faça com que ele cumprimente a pessoa usando seu nome completo. 223 | END_PARAGRAPH 224 | end 225 | para do <<-END_PARAGRAPH 226 | • Escreva um programa que pergunte pelo número favorito de uma 227 | pessoa. Some um ao número, e sugira o resultado como um número favorito 228 | muito melhor (tenha tato ao fazê-lo). 229 | END_PARAGRAPH 230 | end 231 | para do <<-END_PARAGRAPH 232 | Assim que você terminar esses dois programas (e quaisquer outros que 233 | você queira tentar), aprenderemos mais #{makeLink('métodos', :generateMethods)} (e mais coisas sobre eles). 234 | END_PARAGRAPH 235 | end 236 | end 237 | end 238 | -------------------------------------------------------------------------------- /lib/learn_to_program_tutorial/flow_control.rb: -------------------------------------------------------------------------------- 1 | module FlowControl 2 | # 3 | # FLOW CONTROL 4 | # 5 | 6 | def generateFlowControl 7 | para do <<-END_PARAGRAPH 8 | Ahhhh, controle de fluxo. É aqui que tudo se junta. Ainda que 9 | este capítulo seja mais curto e fácil que o capítulo sobre 10 | #{makeLink 'métodos', :generateMethods}, ele vai abrir um mundo de 11 | possibilidades de programação. 12 | Após este capítulo, poderemos escrever programas realmente interativos; 13 | antes fizemos programas que dizem coisas diferentes 14 | dependendo do que você escreve, mas após este capítulo eles 15 | farão coisas diferentes, também. Todavia, temos que poder 16 | comparar objetos no nosso programa. Precisamos de... 17 | END_PARAGRAPH 18 | end 19 | h2 {'Métodos de Comparação'} 20 | para do <<-END_PARAGRAPH 21 | Vamos ser rápidos por aqui para chegar até as ramificações, 22 | que é onde as coisas legais começam a acontecer. 23 | Para ver se um objeto é maior ou menor que outro, usamos 24 | os métodos #{code '>'} e #{code '<'}, assim: 25 | END_PARAGRAPH 26 | end 27 | prog do <<-END_CODE 28 | puts 1 > 2 29 | puts 1 < 2 30 | END_CODE 31 | end 32 | para do <<-END_PARAGRAPH 33 | Tudo em ordem. Do mesmo modo, podemos descobrir se um objeto 34 | é maior-ou-igual-que (ou menor-ou-igual-que) outro com os métodos 35 | #{code '>='} e #{code '<='}. 36 | END_PARAGRAPH 37 | end 38 | prog do <<-END_CODE 39 | puts 5 >= 5 40 | puts 5 <= 4 41 | END_CODE 42 | end 43 | para do <<-END_PARAGRAPH 44 | Por fim, podemos descobrir se dois objetos são iguais 45 | ou não usando #{code '=='} (que significa "estes objetos são iguais?") 46 | e #{code '!='} (que significa "estes objetos são diferentes?"). 47 | É importante não confundir #{code '='} com #{code '=='}. #{code '='} 48 | serve para dizer a uma variável que aponte para um objeto 49 | (atribuição), e #{code '=='} é para fazer a pergunta: "Estes dois 50 | objetos são iguais?". 51 | END_PARAGRAPH 52 | end 53 | prog do <<-END_CODE 54 | puts 1 == 1 55 | puts 2 != 1 56 | END_CODE 57 | end 58 | para do <<-END_PARAGRAPH 59 | E é claro que também podemos comparar strings. Quando strings 60 | são comparadas, leva-se em conta seus ordenamentos 61 | lexicográficos, que, trocando em miúdos, significa a ordem delas 62 | no dicionário. #{code 'cachorro'} vem antes de #{code 'gato'} no 63 | dicionário, então: 64 | END_PARAGRAPH 65 | end 66 | prog do <<-END_CODE 67 | puts 'cachorro' < 'gato' 68 | END_CODE 69 | end 70 | para do <<-END_PARAGRAPH 71 | Há um porém: os computadores costumam ordenar letras 72 | maiúsculas antes de minúsculas, como se viessem antes (é assim que 73 | guardam as letras em fontes, por exemplo: todas as letras 74 | maiúsculas primeiro, seguidas das minúsculas). 75 | Isso significa que o computador vai pensar que #{code "'Zoológico'"} vem 76 | antes de #{code "'abelha'"}, então se você quiser descobrir qual 77 | palavra viria primeiro num dicionário de verdade, use #{code 'downcase'} 78 | (ou #{code 'upcase'} ou #{code 'capitalize'}) em ambas as palavras 79 | antes de tentar compará-las. 80 | END_PARAGRAPH 81 | end 82 | para do <<-END_PARAGRAPH 83 | Uma última observação antes de Ramificações: os 84 | métodos de comparação não estão nos dando as strings #{code "'true'"} 85 | e #{code "'false'"}; elas estão nos dando os objetos especiais 86 | #{code 'true'} e #{code 'false'} (claro, #{code 'true.to_s'} nos dá 87 | #{code "'true'"}, que é como #{code 'puts'} imprimiu #{code "'true'"}). 88 | #{code 'true'} e #{code 'false'} são usados o tempo todo em... 89 | END_PARAGRAPH 90 | end 91 | h2 {'Ramificações (Branching)'} 92 | para do <<-END_PARAGRAPH 93 | "Ramificação" é um conceito simples, mas poderoso. Na verdade, 94 | é tão simples que aposto que nem tenho que explicá-lo; deixa 95 | eu mostrar para você: 96 | END_PARAGRAPH 97 | end 98 | executa1 = {:input => ['Chris']} 99 | executa2 = {:input => ['Chewbacca'], :remark => 'Mas se colocarmos um nome diferente...'} 100 | progN executa1, executa2 do <<-END_CODE 101 | puts 'Olá, qual é o seu nome?' 102 | nome = gets.chomp 103 | puts 'Olá, ' + nome + '.' 104 | if nome == 'Chris' 105 | puts 'Que nome bonito!' 106 | end 107 | END_CODE 108 | end 109 | para do <<-END_PARAGRAPH 110 | E isso é ramificar. Se o que vem depois de #{code 'if'} (N.T.—se) é 111 | #{code 'true'}, nós executamos o código entre #{code 'if'} e 112 | #{code 'end'}. Se o que vem depois de #{code 'if'} é #{code 'false'}, 113 | não executamos nada. Claro e simples. 114 | END_PARAGRAPH 115 | end 116 | para do <<-END_PARAGRAPH 117 | Eu indentei o código entre #{code 'if'} e #{code 'end'} porque 118 | acho que fica mais fácil acompanhar as ramificações assim. Quase 119 | todos os programadores fazem isso, independente da linguagem 120 | em que estejam trabalhando. Pode não parecer muito útil neste 121 | exemplo pequeno, mas quando as coisas ficam mais complexas, 122 | faz uma baita diferença. 123 | END_PARAGRAPH 124 | end 125 | para do <<-END_PARAGRAPH 126 | Muitas vezes gostaríamos que um programa fizesse uma coisa se 127 | uma expressão for #{code 'true'}, e outra se for #{code 'false'}. 128 | É para isso que serve #{code 'else'}: 129 | END_PARAGRAPH 130 | end 131 | executa1 = {:input => ['Chris']} 132 | executa2 = {:input => ['Ringo'], :remark => 'Agora vamos tentar um nome diferente...'} 133 | progN executa1, executa2 do <<-END_CODE 134 | puts 'Eu sou um vidente. Diga-me seu nome:' 135 | nome = gets.chomp 136 | if nome == 'Chris' 137 | puts 'Vejo coisas maravilhosas no seu futuro.' 138 | else 139 | puts 'Seu futuro é... Ó, Deus! Olha a hora!' 140 | puts 'Eu tenho que ir, mil perdões!' 141 | end 142 | END_CODE 143 | end 144 | para do <<-END_PARAGRAPH 145 | Ramificar é como deparar com uma bifurcação no código: tomamos 146 | o caminho para as pessoas com o #{code "nome == 'Chris'"} ou 147 | #{code 'else'}, tomamos o outro caminho? 148 | END_PARAGRAPH 149 | end 150 | para do <<-END_PARAGRAPH 151 | E como os galhos de uma árvore, você pode ter ramificações 152 | que contêm suas próprias ramificações: 153 | END_PARAGRAPH 154 | end 155 | executa1 = {:input => ['chris', 'sim']} 156 | executa2 = {:input => ['Chris'], :remark => 'Está bem, vou capitalizar...'} 157 | progN executa1, executa2 do <<-END_CODE 158 | puts 'Olá, e bem-vindo à aula de Português.' 159 | puts 'Meu nome é professora Hélia. Seu nome é...?' 160 | nome = gets.chomp 161 | 162 | if nome == nome.capitalize 163 | puts 'Por favor, sente-se, ' + nome + '.' 164 | else 165 | puts nome + '? Você quer dizer ' + nome.capitalize + ', não é?' 166 | puts 'Você não sabe nem escrever seu nome??' 167 | resposta = gets.chomp 168 | 169 | if resposta.downcase == 'sim' 170 | puts 'Hunf! Vá, sente-se!' 171 | else 172 | puts 'FORA!!!' 173 | end 174 | end 175 | END_CODE 176 | end 177 | para do <<-END_PARAGRAPH 178 | Às vezes pode ficar confuso entender onde colocar os 179 | #{code 'if'}s, #{code 'else'}s e #{code 'end'}s. O que eu faço 180 | é escrever o #{code 'end'} ao mesmo tempo que escrevo 181 | o #{code 'if'}. Então enquanto eu estava escrevendo o programa 182 | acima, ele estava primeiro assim: 183 | END_PARAGRAPH 184 | end 185 | prog false do <<-END_CODE 186 | puts 'Olá, e bem-vindo à aula de Português.' 187 | puts 'Meu nome é professora Hélia. Seu nome é...?' 188 | nome = gets.chomp 189 | 190 | if nome == nome.capitalize 191 | else 192 | end 193 | END_CODE 194 | end 195 | para do <<-END_PARAGRAPH 196 | Aí eu preenchi com comentários, coisas no 197 | código que o computador irá ignorar: 198 | END_PARAGRAPH 199 | end 200 | prog false do <<-END_CODE 201 | puts 'Olá, e bem-vindo à aula de Português.' 202 | puts 'Meu nome é professora Hélia. Seu nome é...?' 203 | nome = gets.chomp 204 | 205 | if nome == nome.capitalize 206 | # Ela é cordial. 207 | else 208 | # Ela fica brava. 209 | end 210 | END_CODE 211 | end 212 | para do <<-END_PARAGRAPH 213 | Qualquer coisa após um #{code '#'} é considerado um comentário (a 214 | não ser, é claro, que você esteja em uma string). Depois de preencher 215 | com comentários, substituí-os por código funcional. Algumas 216 | pessoas gostam de deixá-los no arquivo; particularmente, creio 217 | que código bem-escrito fala por si. Eu costumava escrever 218 | mais comentários, mas quanto mais "fluente" fico em Ruby, menos 219 | faço uso deles. Eles me distraem boa parte do tempo. É uma escolha 220 | individual; você vai encontrar o seu estilo (normalmente em 221 | constante evolução). Então meu próximo passo ficou assim: 222 | END_PARAGRAPH 223 | end 224 | prog false do <<-END_CODE 225 | puts 'Olá, e bem-vindo à aula de Português.' 226 | puts 'Meu nome é professora Hélia. Seu nome é...?' 227 | nome = gets.chomp 228 | 229 | if nome == nome.capitalize 230 | puts 'Por favor, sente-se, ' + nome + '.' 231 | else 232 | puts nome + '? Você quer dizer ' + nome.capitalize + ', não é?' 233 | puts 'Você não sabe nem escrever seu nome??' 234 | resposta = gets.chomp 235 | 236 | if resposta.downcase == 'sim' 237 | else 238 | end 239 | end 240 | END_CODE 241 | end 242 | para do <<-END_PARAGRAPH 243 | Mais uma vez escrevi #{code 'if'}, #{code 'else'} e #{code 'end'} 244 | ao mesmo tempo. Realmente me ajuda a saber "onde estou" no código. 245 | Também faz com que o trabalho pareça mais fácil porque posso me 246 | concentrar em uma parte pequena, como preencher o código entre 247 | #{code 'if'} e #{code 'else'}. Uma outra vantagem de fazê-lo 248 | desta maneira é que o computador pode entender o programa em 249 | qualquer estágio. Qualquer uma das versões inacabadas do 250 | programa que eu lhe mostrei rodariam. Elas não estavam terminadas, 251 | mas eram programas funcionais. Desta maneira eu pude testar 252 | enquanto escrevia, o que me ajudou a ver como o programa 253 | progredia e o que precisava ser melhorado. Quando ele passou 254 | em todos os testes, eu soube que estava pronto! 255 | END_PARAGRAPH 256 | end 257 | para do <<-END_PARAGRAPH 258 | Essas dicas vão ajudá-lo a escrever programas que se ramificam, 259 | mas também ajudam com outro tipo central de controle de fluxo: 260 | END_PARAGRAPH 261 | end 262 | h2 {'Repetição (Looping)'} 263 | para do <<-END_PARAGRAPH 264 | Você vai querer com alguma freqüência que o computador faça a mesma 265 | coisa várias e várias vezes—afinal, é nisso que os computadores, 266 | em teoria, são bons. 267 | END_PARAGRAPH 268 | end 269 | para do <<-END_PARAGRAPH 270 | Quando você manda o seu computador ficar repetindo algo, você 271 | também precisa dizê-lo quando parar. Computadores nunca se entediam, 272 | então se você não mandar o seu parar, ele não parará. Garantimos 273 | que isso não aconteça ao dizermos que ele deve repetir certas partes 274 | de um programa #{code 'while'} (N.T.—enquanto) uma condição 275 | especificada for verdadeira. O funcionamento é bem parecido com o do 276 | #{code 'if'}: 277 | END_PARAGRAPH 278 | end 279 | prog ['Olá?', 'Oi!', 'Muito prazer em conhecê-lo.', 'Ah... que amor!', 'tchau'] do <<-END_CODE 280 | comando = '' 281 | 282 | while comando != 'tchau' 283 | puts comando 284 | comando = gets.chomp 285 | end 286 | 287 | puts 'Volte logo!' 288 | END_CODE 289 | end 290 | para do <<-END_PARAGRAPH 291 | E isso é um loop (você deve ter notado a linha em branco no começo 292 | da saída; ela vem do primeiro #{code 'puts'}, antes do primeiro 293 | #{code 'gets'}. Como você modificaria o programa para se livrar 294 | dessa primeira linha? Teste! Funcionou exatamente como o 295 | programa acima, fora aquela primeira linha em branco?). 296 | END_PARAGRAPH 297 | end 298 | para do <<-END_PARAGRAPH 299 | Loops, ou repetições, permitem que você faça várias coisas 300 | interessantes, como sei que você pode imaginar. Mas também 301 | podem causar problemas se você cometer algum erro. E se o computador 302 | ficar preso num loop infinito? Se você acha que isso pode ter acontecido, 303 | é só segurar a tecla Ctrl e pressionar C. 304 | END_PARAGRAPH 305 | end 306 | para do <<-END_PARAGRAPH 307 | Antes de começarmos a brincar com loops, vamos aprender algumas 308 | coisinhas para facilitar nossa vida. 309 | END_PARAGRAPH 310 | end 311 | h2 {'Um Pouco de Lógica'} 312 | para do <<-END_PARAGRAPH 313 | Vamos dar uma olhada no nosso primeiro programa com ramificações. E 314 | se minha esposa chegasse em casa, visse o programa, tentasse usá-lo 315 | e ele não dissesse que nome bonito ela tem? Eu não 316 | gostaria de magoá-la (ou de dormir no sofá), então vamos reescrevê-lo: 317 | END_PARAGRAPH 318 | end 319 | prog ['Katy'] do <<-END_CODE 320 | puts 'Olá, qual é o seu nome?' 321 | nome = gets.chomp 322 | puts 'Olá, ' + nome + '.' 323 | if nome == 'Chris' 324 | puts 'Que nome bonito!' 325 | else 326 | if nome == 'Katy' 327 | puts 'Que nome bonito!' 328 | end 329 | end 330 | END_CODE 331 | end 332 | para do <<-END_PARAGRAPH 333 | Bom, funciona... mas não é lá um programa muito bonito. E por quê? 334 | A melhor regra que eu aprendi sobre programação foi a regra 335 | DRY: Don't Repeat Yourself 336 | (N.T.—Não Se Repita). Eu poderia escrever um livro só sobre 337 | o quão boa ela é. No nosso caso, repetimos a linha 338 | #{code 'Que nome bonito!'}. Por que é que isso é um problema? Bem, 339 | e se eu cometi um erro de digitação quando eu reescrevi? E se eu 340 | quisesse mudar de #{code 'bonito'} para #{'gracioso'} em ambas 341 | as linhas? Eu sou preguiçoso, lembra? Basicamente, se eu quero 342 | que meu programa faça a mesma coisa quando receber #{code 'Chris'} ou 343 | #{code 'Katy'}, então ele realmente deve fazer a mesma coisa: 344 | END_PARAGRAPH 345 | end 346 | prog ['Katy'] do <<-END_CODE 347 | puts 'Olá, qual é o seu nome?' 348 | nome = gets.chomp 349 | puts 'Olá, ' + nome + '.' 350 | if (nome == 'Chris' or nome == 'Katy') 351 | puts 'Que nome bonito!' 352 | end 353 | END_CODE 354 | end 355 | para do <<-END_PARAGRAPH 356 | Muito melhor. Para que funcionasse, usei #{code 'or'}. Os outros 357 | operadores lógicos são #{code 'and'} e #{code 'not'}. É 358 | sempre bom usar parênteses ao trabalhar com eles. Vamos ver como 359 | funcionam: 360 | END_PARAGRAPH 361 | end 362 | prog do <<-END_CODE 363 | euSouChris = true 364 | euSouRoxo = false 365 | euAmoComida = true 366 | euComoPedras = false 367 | 368 | puts (euSouChris and euAmoComida) 369 | puts (euAmoComida and euComoPedras) 370 | puts (euSouRoxo and euAmoComida) 371 | puts (euSouRoxo and euComoPedras) 372 | puts 373 | puts (euSouChris or euAmoComida) 374 | puts (euAmoComida or euComoPedras) 375 | puts (euSouRoxo or euAmoComida) 376 | puts (euSouRoxo or euComoPedras) 377 | puts 378 | puts (not euSouRoxo) 379 | puts (not euSouChris) 380 | END_CODE 381 | end 382 | para do <<-END_PARAGRAPH 383 | O único deles que pode enganá-lo é #{code 'or'} (N.T.—ou). 384 | Em português, usa-se "ou" para dizer "um ou outro, mas não os dois". 385 | Por exemplo, sua mãe pode lhe dizer: "Para sobremesa você pode escolher 386 | torta ou bolo". Ela não deu a opção de escolher os dois! 387 | Um computador, por outro lado, entende #{code 'or'} como "ou um ou outro, 388 | ou os dois" (outro jeito de colocar é "ao menos um destes é verdadeiro"). 389 | É por isso que computadores são mais legais que mães. 390 | END_PARAGRAPH 391 | end 392 | h2 {'Umas Coisinhas Para Tentar'} 393 | para do <<-END_PARAGRAPH 394 | • "Um elefante incomoda muita gente..." Escreva um 395 | programa que imprima a letra para o clássico das viagens de 396 | carro, com um limite de 100 elefantes. 397 | END_PARAGRAPH 398 | end 399 | para do <<-END_PARAGRAPH 400 | • Escreva um programa Velha Surda. O que quer que 401 | você diga à velha (o que quer que você digite), ela tem 402 | que responder com #{output 'QUE?! FALA MAIS ALTO!'}, a não 403 | ser que você grite (digite tudo em maiúsculas). Se você 404 | gritar, ela pode lhe ouvir (ou ao menos pensa que pode), e 405 | sempre responde #{output 'NÃO, NÃO DESDE 1938!'} Para fazer seu 406 | programa ser realmente verossímil, faça a velha gritar 407 | um número diferente a cada vez; talvez qualquer ano aleatório 408 | entre 1930 e 1950 (a última parte é opcional, e ficaria muito 409 | mais fácil se você lesse a seção sobre o gerador de números 410 | randômicos do Ruby no capítulo sobre 411 | #{makeLink 'métodos', :generateMethods}). Você não pode parar 412 | de falar com a velha enquanto não gritar #{input 'TCHAU'}.
413 | Dica: Não esqueça do #{code 'chomp'} 414 | ! #{code "'TCHAU'"} com um enter não é a mesma coisa que 415 | #{code "'TCHAU'"} sem! 416 | Dica 2: Tente pensar em que partes do programa 417 | as coisas acontecem repetidamente. Todas elas devem estar no seu 418 | loop #{code 'while'}. 419 | END_PARAGRAPH 420 | end 421 | para do <<-END_PARAGRAPH 422 | • Melhore o seu programa Velha Surda: e se a velha 423 | não quiser que você vá embora? Quando você gritar #{input 'TCHAU'}, 424 | ela pode fingir que não lhe ouve. Mude seu programa anterior 425 | para que você tenha que gritar #{input 'TCHAU'} três vezes em 426 | seqüência. Teste bem o seu programa: se você gritar 427 | #{input 'TCHAU'} três vezes, mas não em seqüência, você tem 428 | que continuar falando com a velha. 429 | END_PARAGRAPH 430 | end 431 | para do <<-END_PARAGRAPH 432 | • Anos bissextos. Escreva um programa que pergunte um 433 | ano inicial e um ano final, e imprima com #{code 'puts'} todos 434 | os anos bissextos entre eles (e os incluindo, se eles também 435 | forem bissextos). Anos bissextos são sempre divisíveis por 436 | quatro (como 1984 e 2004). Contudo, anos divisíveis por 100 437 | não são bissextos (como 1800 e 1900) 438 | a não ser que sejam divisíveis por 439 | 400 (como 1600 e 2000, que foram de fato anos bissextos). 440 | (Sim, é bem confuso, mas não tão confuso como ter dezembro 441 | no meio do inverno, que é o que aconteceria no fim). 442 | END_PARAGRAPH 443 | end 444 | para do <<-END_PARAGRAPH 445 | Quando você terminá-las, descanse um pouco! Você já aprendeu 446 | muitas coisas. Parabéns. Você está surpreso com a quantidade 447 | de coisas que se pode mandar o computador fazer? Mais alguns capítulos 448 | e você vai poder programar praticamente tudo. Sério mesmo! 449 | Veja só tudo que você pode fazer que não podia antes de aprender 450 | sobre loops e ramificações. 451 | END_PARAGRAPH 452 | end 453 | para do <<-END_PARAGRAPH 454 | Agora vamos aprender sobre um novo tipo de objeto, que 455 | controla listas de outros objetos: 456 | #{makeLink 'arrays', :generateArrays}. 457 | END_PARAGRAPH 458 | end 459 | end 460 | end 461 | -------------------------------------------------------------------------------- /lib/learn_to_program_tutorial/formatting_page.rb: -------------------------------------------------------------------------------- 1 | module FormattingPage 2 | # 3 | # PÁGINA DE TESTE PARA FORMATAÇÃO 4 | # 5 | 6 | def generateFormattingPage 7 | h1 { 'Cabeçalho 1' } 8 | h2 { 'Cabeçalho 2' } 9 | h3 { 'Cabeçalho 3' } 10 | h4 { 'Cabeçalho 4' } 11 | 12 | para {'Aqui está um código com uma saída falsa:'} 13 | prog [], '...brincadeirinha, cara...', 'FANTÁSTICO!' do <<-'END_CODE' 14 | # Aqui está um código 'Ruby'. 15 | # 5 é melhor do que 6. 16 | # def wilma do end if not in, cara. 17 | #' 18 | 19 | '#Isto não deveria causar nenhum problema.' 20 | 'Nem # deveria isto\\' 21 | 'do end if elsif else case when then while def class' 22 | 'or and not next in' 23 | 'to 3 or not to 3, that is 3.7' 24 | '' + 'x'+''+''+'..' 25 | '' +'o' 26 | 27 | 8 28 | 0.09 29 | 9.9 30 | 5.times {} 31 | 32 | puts 'Eu adoro queijo.' # yo 'g' 33 | puts 5.02 + 8 + 0.002 # s'up, muva 34 | 35 | jimmy = ['yoyoyo', 66] 36 | jimmy.each do |item| 37 | puts item.inspect 38 | end 39 | 40 | puts case 'abobora' 41 | when String then 'sim' 42 | when Fixnum then 'nao' 43 | else 'talvez' 44 | end 45 | 46 | def yummy 47 | if (4 <= 5) 48 | 'Uhmmm!' 49 | elsif (4 == 5) 50 | 'Ãh?' 51 | else 52 | while (1 == 2) 53 | puts 'O quê?' 54 | end 55 | end 56 | end 57 | 58 | class ApenasAlgumaClasse 59 | def initialize 60 | @var = 5 61 | end 62 | end 63 | 64 | puts Math::PI # Deveria funcionar. 65 | puts PI # Não deveria funcionar. 66 | END_CODE 67 | end 68 | para {'Aqui está um código com entrada e saída:'} 69 | prog ['"Chris"', '&26', ''] do <<-END_CODE 70 | puts 'yoyo...wuddup?' 71 | puts 'NOME:' 72 | name = gets.chomp 73 | puts 'IDADE:' 74 | age = gets.chomp 75 | puts 'COR FAVORITA' 76 | color = gets.chomp 77 | puts 'Olá, '+name+', amante da cor '+color+' de '+age+' anos de idade. ' 78 | END_CODE 79 | end 80 | 81 | para do <<-END_PARAGRAPH 82 | Olá. Eu adoro #{input 'colocar VÁRIAS coisas'}. Eu também fico animado 83 | de #{code 'codificar várias coisas'}. Existe uma tal emoção em 84 | ver tudo da excitante #{output 'saída que você pode obter'} de um 85 | programa bem escrito. 86 | END_PARAGRAPH 87 | end 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /lib/learn_to_program_tutorial/learn_to_program.rb: -------------------------------------------------------------------------------- 1 | module LearnToProgram 2 | 3 | def initialize (cgi) 4 | @cgi = cgi 5 | @depth = 0 6 | @page = [] 7 | 8 | # 'format' é uma página escondida para testar a formatação. 9 | @chapters = {'format'=>['Página de Formatação', :generateFormattingPage]} 10 | @chapters['00' ] = ['Iniciando', :generateSetup] 11 | @chapters['01' ] = ['Números', :generateNumbers] 12 | @chapters['02' ] = ['Letras', :generateLetters] 13 | @chapters['03' ] = ['Variáveis e Atribuições', :generateVariables] 14 | @chapters['04' ] = ['Misturando tudo', :generateConversion] 15 | @chapters['05' ] = ['Mais Sobre Métodos', :generateMethods] 16 | @chapters['06' ] = ['Controle de Fluxo', :generateFlowControl] 17 | @chapters['07' ] = ['Arrays e Iteradores', :generateArrays] 18 | @chapters['08' ] = ['Escrevendo seus Próprios Métodos', :generateDefMethod] 19 | @chapters['09' ] = ['Classes', :generateClasses] 20 | @chapters['10' ] = ['Blocos e Procs', :generateBlocksProcs] 21 | @chapters['11' ] = ['Além deste Tutorial', :generateBeyond] 22 | end 23 | 24 | def getChapter (method) 25 | @chapters.each do |num, chapter| 26 | return num if (method == chapter[1]) 27 | end 28 | 'Main' 29 | end 30 | 31 | def selfLink (chap = nil) 32 | # REQUEST_URI includes "?Chapter=Foo" 33 | LINKADDR+'index.rb?Chapter='+(chap ? getChapter(chap) : '') 34 | end 35 | 36 | def makeLink (name, methodName) 37 | ''+name+'' 38 | end 39 | 40 | def out 41 | @cgi.out { @page.join("\n")+"\n" } 42 | end 43 | 44 | def puts (string, escapeThis=false) 45 | if escapeThis 46 | string = CGI::escapeHTML string 47 | end 48 | @page << ' '*@depth+string 49 | end 50 | 51 | def escapeOutputNotInput (output) 52 | md = /#{INPUT}.*?#{INPUT.reverse}/.match output 53 | if md 54 | CGI::escapeHTML(md.pre_match) + 55 | CGI::escapeHTML(md[0]).sub(/#{INPUT}/,'').sub(/#{INPUT.reverse}/,'') + 56 | escapeOutputNotInput(md.post_match) 57 | else 58 | CGI::escapeHTML output 59 | end 60 | end 61 | 62 | def syntaxColor (str) # str provavelmente possui html-escaped. 63 | lines = str.split /\n/ 64 | # L2Pcomment 65 | # L2Pstring 66 | # L2Pnumber 67 | # L2Pkeyword 68 | # L2Pdefinition 69 | 70 | lines.collect! do |line| 71 | #line += ' ' # para dividir... Precisamos disso? 72 | md = /'|#/.match line 73 | if md # Comment or string. 74 | syntaxColor(md.pre_match) + 75 | if (md[0] == '#') 76 | '' + md[0] + md.post_match + '' 77 | else # Big string time... 78 | md2 = /(.*?)(^|[^\\])((\\\\)*)'/.match md.post_match 79 | if (md2) 80 | md[0] + '' + $1 + $2 + $3 + 81 | '' + "'" + syntaxColor(md2.post_match) 82 | else 83 | md[0] 84 | end 85 | end 86 | else # sem comentários nem string. 87 | keywords = %w[__FILE__ and end in or self unless __LINE__ 88 | begin ensure redo super until BEGIN break do 89 | false next rescue then when END case else for 90 | nil retry true while alias elsif if not 91 | return undef yield] 92 | 93 | keywords.each do |keyword| 94 | line.gsub!(/(\W|^)(#{keyword})(\W|$)/) do 95 | $1+''+$2+''+$3 96 | end 97 | end 98 | 99 | ['def', 'class', 'module'].each do |keyword| 100 | line.gsub!(/(\W|^)(#{keyword}) +([\w?]+)/) do 101 | $1+'' +$2+''+ 102 | ' '+$3+'' 103 | end 104 | end 105 | 106 | line.gsub!(/(^|[-{\[( ^+%*\/?;])(\d+(\.\d+)?|\.\d+)/) do 107 | $1+''+$2+'' 108 | end 109 | 110 | line 111 | end 112 | end 113 | 114 | lines.join "\n" 115 | end 116 | 117 | 118 | def input (str) 119 | str = CGI::escapeHTML str 120 | str.gsub!(/ /, ' ') 121 | ''+str+'' 122 | end 123 | 124 | def code (str) 125 | str = CGI::escapeHTML str 126 | str.gsub!(/ /, ' ') 127 | str = syntaxColor str 128 | ''+str+'' 129 | end 130 | 131 | def output (str) 132 | str = CGI::escapeHTML str 133 | str.gsub!(/ /, ' ') 134 | ''+str+'' 135 | end 136 | 137 | # Essa é a parte legal... 138 | def executeCode (code, input) 139 | # Encapsula o código para pegar erros e não ocorrer SystemExit. 140 | code = <<-END_CODE 141 | begin 142 | #{code} 143 | rescue SystemExit 144 | rescue Exception => error 145 | puts error.inspect 146 | end 147 | END_CODE 148 | 149 | strIO = StringIO.new 150 | 151 | if !input.empty? 152 | input = input.join("\n")+"\n" 153 | input = StringIO.new(input, "r") 154 | class << strIO; self; end.module_eval do 155 | ['gets', 'getc', 'read'].each do |meth| 156 | define_method(meth) do |*params| 157 | inStr = input.method(meth).call(*params) 158 | puts INPUT+inStr.chomp+(INPUT.reverse) # Echo input. 159 | inStr 160 | end 161 | end 162 | end 163 | end 164 | 165 | # Passa esses métodos para strIO: 166 | kernelMethods = ['puts', 'putc', 'gets'] 167 | 168 | # Métodos de Swap out Kernel... 169 | kernelMethods.each do |meth| 170 | Kernel.module_eval "alias __temp__tutorial__#{meth}__ #{meth}" 171 | Kernel.module_eval do 172 | define_method(meth) do |*params| 173 | strIO.method(meth).call(*params) 174 | end 175 | end 176 | end 177 | 178 | begin 179 | strIO.instance_eval code 180 | rescue Exception => error # Captura erros durante o parse. 181 | return error.inspect 182 | end 183 | 184 | # ...e faz o swap de volta. 185 | kernelMethods.each do |meth| 186 | Kernel.module_eval "alias #{meth} __temp__tutorial__#{meth}__" 187 | end 188 | 189 | strIO.string 190 | end 191 | 192 | 193 | # Tags (ou similar) 194 | 195 | def para (attributes = {}, &block) 196 | method_missing(:p, attributes, &block) 197 | end 198 | 199 | def prog (execute = [], remark = nil, fakeOutput = nil, &block) 200 | if !execute 201 | return progN(&block) 202 | end 203 | 204 | run = {:input => execute} 205 | run[:remark ] = remark if remark 206 | run[:fakeOutput] = fakeOutput if fakeOutput 207 | progN(run, &block) 208 | end 209 | 210 | def progN (*trialRuns) 211 | code = yield 212 | 213 | # Retirando espaços em branco. 214 | lines = code.split $/ 215 | numSpaces = lines[0].length - lines[0].sub(/ */, '').length 216 | lines.each do |line| 217 | line.sub!(/ {0,#{numSpaces}}/, '') 218 | end 219 | code = lines.join($/) 220 | 221 | prettyCode = syntaxColor(CGI::escapeHTML(code)) 222 | 223 | # Spit it out. 224 | puts '
'+prettyCode+'
' 225 | 226 | trialRuns.each do |run| 227 | if run[:fakeOutput] 228 | puts '
'+CGI::escapeHTML(run[:fakeOutput])+'
' 229 | end 230 | if run[:remark] 231 | puts '

'+run[:remark]+'

' 232 | end 233 | output = escapeOutputNotInput(executeCode(code,run[:input])) 234 | puts '
'+$/+output+'
' 235 | end 236 | nil 237 | end 238 | 239 | # Cria uma tag. 240 | def method_missing (methodSymbol, attributes = {}) 241 | methodName = methodSymbol.to_s 242 | 243 | attribString = '' 244 | attributes.each do |key, val| 245 | raise methodName if (key.nil? || val.nil?) 246 | attribString += ' '+key.to_s+'="'+val+'"' 247 | end 248 | if (!block_given?) 249 | puts '<'+methodName+attribString+' />' 250 | else 251 | puts '<'+methodName+attribString+'>' 252 | @depth += 1 253 | blockReturn = yield 254 | puts blockReturn if (blockReturn.kind_of?(String)) 255 | @depth -= 1 256 | puts '' 257 | end 258 | nil 259 | end 260 | 261 | def self.included(base) 262 | base.extend(LearnToProgram::ClassMethods) 263 | end 264 | 265 | module ClassMethods 266 | def handle_request cgi 267 | begin 268 | if cgi.params['ShowTutorialCode'][0] 269 | tutorialSource = File.read __FILE__ 270 | cgi.out('text/plain') { tutorialSource } 271 | else 272 | page = self.new cgi 273 | page.generate 274 | page.out 275 | end 276 | rescue Exception => e 277 | error_msg = <<-END_ERROR 278 | ERRO 279 |

ERRO: envie um e-mail para o Chris ou para a Katy com o seguinte endereço

280 |
#{e.class}:  #{CGI::escapeHTML(e.message)}
281 |           #{e.backtrace.join("\n")}
282 |           
283 | 284 | END_ERROR 285 | cgi.out { error_msg } 286 | end 287 | end 288 | end 289 | end 290 | -------------------------------------------------------------------------------- /lib/learn_to_program_tutorial/letters.rb: -------------------------------------------------------------------------------- 1 | module Letters 2 | # 3 | # LETTERS 4 | # 5 | 6 | def generateLetters 7 | para do <<-END_PARAGRAPH 8 | Então, nós já aprendemos tudo sobre #{makeLink('números', :generateNumbers)}, 9 | mas e as letras? Palavras? Textos? 10 | END_PARAGRAPH 11 | end 12 | para do <<-END_PARAGRAPH 13 | Nós nos referimos a grupos de letras em um programa como strings (Você 14 | pode pensar em letras impressas juntas ao longo de um banner). 15 | Para ficar mais fácil de entender quais partes do código são strings, 16 | Eu vou colorir as strings em #{STRING_COLOR}. 17 | Aqui tem alguns exemplos de strings: 18 | END_PARAGRAPH 19 | end 20 | prog false do <<-END_CODE 21 | 'Olá.' 22 | 'Ruby rocks.' 23 | '5 é meu número favorito... qual é o seu?' 24 | 'Snoopy diz #%^?&*@! quando alguém pisa no seu pé.' 25 | ' ' 26 | '' 27 | END_CODE 28 | end 29 | para do <<-END_PARAGRAPH 30 | Como você pode ver, strings podem ter pontuação, dígitos, símbolos 31 | e espaços... muito mais do que apenas letras. A última string 32 | não tem nada: nós a chamamos de string vazia. 33 | END_PARAGRAPH 34 | end 35 | para do <<-END_PARAGRAPH 36 | Nós estávamos usando #{code 'puts'} para imprimir os números; 37 | vamos tentar ele de novo com algumas strings: 38 | END_PARAGRAPH 39 | end 40 | prog do <<-END_CODE 41 | puts 'Olá, mundo!' 42 | puts '' 43 | puts 'Até logo.' 44 | END_CODE 45 | end 46 | para do <<-END_PARAGRAPH 47 | Isso funcionou bem. Agora, tente umas strings você mesmo. 48 | END_PARAGRAPH 49 | end 50 | h2 {'Aritimética das String'} 51 | para do <<-END_PARAGRAPH 52 | Assim como você pode fazer aritimética com números, você também 53 | pode fazer aritimética com strings! Bem, uma parte dela... você pode 54 | adicionar strings, de qualquer forma. 55 | Vamos tentar adicionar duas strings e ver o que o #{code 'puts'} 56 | faz. 57 | END_PARAGRAPH 58 | end 59 | prog do <<-END_CODE 60 | puts 'Eu gosto de' + 'torta de maçã.' 61 | END_CODE 62 | end 63 | para do <<-END_PARAGRAPH 64 | Ops! Eu esqueci de adicionar um espaço entre #{code "'Eu gosto de'"} e #{code "'torta de maçã.'"}. 65 | Espaços não fazem importância normalmente, mas eles fazem sentido dentro de strings. 66 | (É verdade o que dizem: computadores não fazem o que você quer que eles façam, 67 | apenas o que você manda eles fazerem). Vamos tentar de novo: 68 | END_PARAGRAPH 69 | end 70 | prog do <<-END_CODE 71 | puts 'Eu gosto de ' + 'torta de maçã.' 72 | puts 'Eu gosto de' + ' torta de maçã.' 73 | END_CODE 74 | end 75 | para do <<-END_PARAGRAPH 76 | (Como você pode ver, não importa em qual string eu adicione o espaço.) 77 | END_PARAGRAPH 78 | end 79 | para do <<-END_PARAGRAPH 80 | Então você pode somar strings. Mas você pode, também, multiplicá-las! 81 | (Por um número, de qualquer forma). Veja isso: 82 | END_PARAGRAPH 83 | end 84 | prog [], '(Estou brincando... ele na verdade faz isso:)', 'piscando os olhos dela' do <<-END_CODE 85 | puts 'piscar ' * 4 86 | END_CODE 87 | end 88 | para do <<-END_PARAGRAPH 89 | Se você parar para pensar, isso realmente faz sentido. Afinal, 90 | #{code '7*3'} realmente quer dizer #{code '7+7+7'}, então #{code "'moo'*3"} 91 | apenas significa #{code "'moo'+'moo'+'moo'"}. 92 | END_PARAGRAPH 93 | end 94 | h2 {"#{code '12'} vs #{code "'12'"}"} 95 | para do <<-END_PARAGRAPH 96 | Antes de irmos mais longe, nós devemos ter certeza de que entendemos 97 | a diferença entre números e dígitos. 98 | #{code '12'} é um número, mas #{code "'12'"} é uma string de dois dígitos. 99 | END_PARAGRAPH 100 | end 101 | para do <<-END_PARAGRAPH 102 | Vamos brincar com isso um pouco: 103 | END_PARAGRAPH 104 | end 105 | prog do <<-END_CODE 106 | puts 12 + 12 107 | puts '12' + '12' 108 | puts '12 + 12' 109 | END_CODE 110 | end 111 | para do <<-END_PARAGRAPH 112 | Que tal isso? 113 | END_PARAGRAPH 114 | end 115 | prog do <<-END_CODE 116 | puts 2 * 5 117 | puts '2' * 5 118 | puts '2 * 5' 119 | END_CODE 120 | end 121 | para do <<-END_PARAGRAPH 122 | Esses exemplos foram muito diretos. De qualquer forma, se você não for 123 | muito cauteloso quando misturar strings e números, você pode cair em... 124 | END_PARAGRAPH 125 | end 126 | h2 {'Problemas'} 127 | para do <<-END_PARAGRAPH 128 | Nesse ponto, você já deve ter tentado algumas coisas que 129 | não funcionaram. Se não, aqui tem algumas: 130 | END_PARAGRAPH 131 | end 132 | prog do <<-END_CODE 133 | puts '12' + 12 134 | puts '2' * '5' 135 | END_CODE 136 | end 137 | para do <<-END_PARAGRAPH 138 | Hmmm... Uma mensagem de erro. O problema é que você 139 | não pode, realmente, adicionar um número a uma string, ou 140 | multiplicar uma string por outra string. Isso não faz muito sentido como isso: 141 | END_PARAGRAPH 142 | end 143 | prog false do <<-END_CODE 144 | puts 'Betty' + 12 145 | puts 'Fred' * 'John' 146 | END_CODE 147 | end 148 | para do <<-END_PARAGRAPH 149 | Uma coisa que você deve saber: você pode escrever #{code "'porco'*5"} em um programa, 150 | já que isso apenas quer dizer #{code '5'} conjuntos da string #{code "'porco'"}, todas adicionadas 151 | entre si. Entretanto, 152 | você não pode escrever #{code "5*'porco'"}, já que isso significa #{code "'porco'"} 153 | conjuntos do número #{code '5'}, o que é um pouco insano. 154 | END_PARAGRAPH 155 | end 156 | para do <<-END_PARAGRAPH 157 | Finalmente, e que tal um programa que imprima 158 | #{output 'Isso é um apóstrofo: \''}? Nós podemos tentar isso: 159 | END_PARAGRAPH 160 | end 161 | prog false do <<-END_CODE 162 | puts 'Isso é um apóstrofo: '' 163 | END_CODE 164 | end 165 | para do <<-END_PARAGRAPH 166 | Bem, aquilo não vai funcionar; Eu nem vou tentar executar aquilo. 167 | O computador me disse que nós terminamos com uma string. 168 | (É por isso que é bom ter um editor de texto que tenha 169 | realçador de sintaxe para você). Então, como podemos 170 | fazer com que o computador saiba que nós queremos continuar dentro da string? 171 | Nós temos que escapar o apóstrofo, assim: 172 | END_PARAGRAPH 173 | end 174 | prog do <<-END_CODE 175 | puts 'Isso é um apóstrofo: \\'' 176 | END_CODE 177 | end 178 | para do <<-END_PARAGRAPH 179 | A barra invertida é um caractere de escape. Em outras palavras, se você tem 180 | uma barra invertida seguida de um caractere, isso pode ser, algumas vezes, traduzido 181 | em um novo caractere. As únicas coisas que uma barra invertida escapa, porém, 182 | são o apóstrofo e a própria barra invertida (Se você pensar a respeito, 183 | caracteres de escape devem sempre escapar a si mesmos). 184 | Acho que uns exemplos são bons agora: 185 | END_PARAGRAPH 186 | end 187 | prog do <<-END_CODE 188 | puts 'Isso é um apóstrofo: \\'' 189 | puts 'uma barra invertida no fim da string: \\\\' 190 | puts 'acima\\\\embaixo' 191 | puts 'acima\\embaixo' 192 | END_CODE 193 | end 194 | para do <<-END_PARAGRAPH 195 | Uma vez que a barra invertida não escapaescapa a si mesma, as últimas duas strings são 197 | idênticas. Elas não se parecem no código, mas no seu computador 198 | elas são as mesmas. 199 | END_PARAGRAPH 200 | end 201 | para do <<-END_PARAGRAPH 202 | Se você tiver outra dúvida, apenas 203 | #{makeLink('continue lendo', :generateVariables)}! Eu não posso 204 | responder a todas as questões nesta página. 205 | END_PARAGRAPH 206 | end 207 | end 208 | end 209 | -------------------------------------------------------------------------------- /lib/learn_to_program_tutorial/main.rb: -------------------------------------------------------------------------------- 1 | module Main 2 | # 3 | # MAIN PAGE GENERATION 4 | # 5 | 6 | def generate 7 | srand 8 | chapNum = @cgi.params['Chapter'][0] 9 | chapter = @chapters[chapNum] 10 | chapTitle = 'Aprenda a Programar, por Chris Pine' 11 | if chapter 12 | chapTitle = chapNum + '.  ' if chapNum < 'A' 13 | chapTitle.sub! /^0/, '' 14 | chapTitle += chapter[0] 15 | end 16 | 17 | puts '' 18 | html(:lang=>'pt_br') do 19 | head do 20 | meta('http-equiv'=>"Content-Type", :content=>"text/html; charset=utf-8") 21 | 22 | link(:href=>LINKADDR+'stylesheets/pine.css', :rel=>'Stylesheet', :type=>'text/css', :media=>'screen') 23 | link(:href=>LINKADDR+'stylesheets/tutorial.css', :rel=>'Stylesheet', :type=>'text/css', :media=>'screen, print') 24 | link(:href=>LINKADDR+'stylesheets/print.css', :rel=>'Stylesheet', :type=>'text/css', :media=>'print') 25 | title { chapTitle } 26 | script(:language=>'JavaScript', :src=>'http://www.gvisit.com/record.php?sid=6941c11eba5c874197e2096f9c854106', :type=>'text/javascript') {} 27 | end # head 28 | body do 29 | div(:id=>'pageWidth') do 30 | div(:id=>'headerBar') do 31 | div(:id=>'titlePicContainer') do 32 | puts '' 33 | img(:id=>'titlePic', :width=>'500', :height=>'108', :src=>'images/titleLTP_pt_br.gif', :alt=>'Aprenda a Programar') 34 | puts '' 35 | end 36 | puts '' 37 | puts ' apenas uma figura bonitinha' 39 | puts '' 40 | end 41 | div(:id=>'menuPane') do 42 | img(:id=>'menuSpearTop', :width=>'35', :height=>'38', :src=>'images/spearup_sm.gif') 43 | 44 | menuBookLink 45 | 46 | img(:width=>'64', :height=>'21', :style=>'padding: 30px;', :src=>'images/swirly.gif') 47 | 48 | menuTOC 49 | 50 | img(:id=>'menuSpearBottom', :width=>'36', :height=>'40', :src=>'images/speardown_sm.gif') 51 | end 52 | div(:id=>'contentPane') do 53 | if chapter 54 | if chapter[0] 55 | h1 {chapTitle} 56 | puts HLINE 57 | end 58 | method(chapter[1]).call 59 | else # TOC 60 | h2 { "Notas sobre a tradução em Português Brasileiro"} 61 | para do <<-END_PARAGRAPH 62 | Todo comunidade de programação é formada pelos amantes de computação, que aprendem linguagens 63 | novas no café-da-manhã, mas também uma uma grande parcela de pessoas que foram empolgadas por 64 | nós mas acabam esbarrando na barreira inicial do aprendizado. Felizmente autores como Chris 65 | Pine resolveram atacar este desafio e o resultado que temos é uma excelente material para 66 | programadores iniciantes em Ruby. 67 | END_PARAGRAPH 68 | end 69 | 70 | para do <<-END_PARAGRAPH 71 | Eu, Fabio Akita, surgi 72 | com esta sugestão em Janeiro de 2008. Fiz o anúncio no meu blog e na lista rails-br e foi um 73 | movimento incrívei: dezenas de voluntários se candidataram a ajudar. Graças a isso a tradução 74 | e revisão não durou uma semana! Fico extremamente satisfeito em ter essa amostra da 75 | comunidade se auto-ajudando. Espero ter a oportunidade de conduzir mais trabalhos desta 76 | natureza. 77 | END_PARAGRAPH 78 | end 79 | 80 | para do <<-END_PARAGRAPH 81 | Meus agradecimentos e parabéns aos tradutores/revisores: 82 | Danilo Sato, 83 | Davi Vidal, 84 | Reginaldo Russinholi, 85 | Oliver Azevedo Barnes, 86 | Vitor Peres, 87 | Paulo Fernando Larini, 88 | Massimiliano Giroldi, 89 | Ricardo Yasuda, 90 | Lucas Húngaro, 91 | Anderson Leite. 92 | 93 | Agradeço também a todos que se voluntariaram, mas havia mais colaboradores que capítulos para 94 | traduzir e sobrou gente :-) Acho que é um bom sinal! 95 | END_PARAGRAPH 96 | end 97 | 98 | para do <<-END_PARAGRAPH 99 | Agradecimentos também ao Júlio Santos Monteiro por dar uma "casa" oficial a este trabalho no 100 | web site http://aprendaaprogramar.rubyonrails.com.br. 101 | END_PARAGRAPH 102 | end 103 | 104 | para do <<-END_PARAGRAPH 105 | Esperamos que o resultado deste trabalho seja de grande valia tanto a estudantes quanto 106 | a qualquer um que queira ensinar outros a programar. 107 | END_PARAGRAPH 108 | end 109 | puts HLINE 110 | 111 | h2 { 'Um lugar para o futuro programador começar' } 112 | para do <<-END_PARAGRAPH 113 | Eu acho que tudo isso começou em 2002. Eu estava pensando 114 | em ensinar programação, e como uma grande linguagem como 115 | Ruby seria ótima para aprender a como programar. Quer dizer, nós estávamos 116 | todos excitados com Ruby pelo seu poder, elegância e por ser realmente divertido, 117 | mas me pareceu que ele também seria um excelente guia para aprender a programar. 118 | END_PARAGRAPH 119 | end 120 | para do <<-END_PARAGRAPH 121 | Infelizmente, não havia muita documentação sobre Ruby 122 | destinada aos iniciantes naquela época. Alguns de nós, 123 | na comunidade, estávamos falando sobre como um tutorial 124 | "Ruby for the Nuby" era necessário, 125 | e, mais genericamente, um tutorial ensinando a programar, como um todo. 126 | Quanto mais eu pensava nisso, mais eu tinha a dizer (o que me surpreendeu 127 | um pouco). Até que alguém finalmente disse: "Chris, porque você 128 | não escreve um tutorial ao invés de ficar falando sobre isso?". 129 | Então eu o fiz. 130 | END_PARAGRAPH 131 | end 132 | para do <<-END_PARAGRAPH 133 | E isso não foi muito bom. Eu tive todas essas boas idéias que eram boas 134 | em teoria, mas a real tarefa de fazer um grande tutorial 135 | para não-programadores foi muito mais desafiadora 136 | do que eu poderia prever. (Quer dizer, pareciam boas para mim, mas eu já 137 | sabia como programar.) 138 | END_PARAGRAPH 139 | end 140 | para do <<-END_PARAGRAPH 141 | O que me salvou foi que eu fiz com que fosse fácil para as pessoas 142 | falarem comigo, e eu sempre tentei ajudar as pessoas quando elas empacavam. 143 | Quando eu via um monte de gente empacando em uma parte, 144 | eu a reescrevia. Isso deu muito trabalho, mas lentamente foi se tornando melhor 145 | e melhor. 146 | END_PARAGRAPH 147 | end 148 | para do <<-END_PARAGRAPH 149 | Alguns anos depois, isso estava ficando realmente bom. :-) Tão bom, 150 | na verdade, que eu já estava pronto para anunciar sua finalização e 151 | partir para outra coisa. E justamente nesse instante houve a 152 | oportunidade de transformar esse tutorial em um livro. Uma vez que o básico 153 | já estava pronto, eu achei que não haveria maiores problemas. 154 | Eu apenas precisaria esclarecer umas coisas, adicionar alguns exercícios extras, 155 | talvez mais alguns exemplos, um pouquinho mais de capítulos, enviar ele para 156 | uns 50 revisores... 157 | END_PARAGRAPH 158 | end 159 | para do <<-END_PARAGRAPH 160 | Isso me tomou outro ano, mas agora eu acho que está realmente 161 | muito bom, grande parte graças às centenas 162 | de boas almas que me ajudaram a escrever este livro. 163 | END_PARAGRAPH 164 | end 165 | para do <<-END_PARAGRAPH 166 | O que está nesse site é o tutorial original, quase inalterado 167 | desde 2004. Para o melhor e mais atualizado, você pode 168 | querer dar uma olhada no livro. 169 | END_PARAGRAPH 170 | end 171 | puts HLINE 172 | h2 { 'Notas Para Professores' } 173 | para do <<-END_PARAGRAPH 174 | Há algumas normas de conduta que eu tentei seguir. 175 | Eu acho que elas tornam o processo de aprendizado muito mais suave; 176 | ensinar a programar já é difícil por si só. Se você está 177 | ensinando ou guiando alguém pelas vias hackers, essas idéias podem lhe ajudar também. 178 | END_PARAGRAPH 179 | end 180 | para do <<-END_PARAGRAPH 181 | Primeiramente, eu tentei separar os conceitos o máximo possível, 182 | assim o estudante tem que aprender apenas um conceito de cada vez. 183 | Isso foi difícil no começo, mas um pouco mais fácil 184 | depois que eu peguei a prática. Algumas coisas devem ser faladas 185 | antes de outras, mas eu fiquei impressionado com quão pouca 186 | hierarquia de precedência realmente existe. Eventualmente, eu apenas tive que 187 | seguir uma ordem, e eu tentei arrumar as coisas de tal maneira 188 | que cada nova seção fosse motivada pela anterior. 189 | END_PARAGRAPH 190 | end 191 | para do <<-END_PARAGRAPH 192 | Outro princípio que eu tinha em mente era de ensinar apenas uma maneira 193 | de fazer alguma coisa. Isso é um benefício óbvio em um tutorial 194 | para pessoas que nunca programaram antes. Por um motivo: 195 | é mais fácil aprender uma maneira de fazer uma coisa do que duas. Porém 196 | o benefício mais importante é que quanto menos coisas você 197 | ensinar a um novo programador, mais criativo e esperto 198 | ele tem que ser na programação. Já que muito da programação 199 | é resolução de problemas, torna-se crucial o encorajamento em todos os estágios 200 | possíveis. 201 | END_PARAGRAPH 202 | end 203 | para do <<-END_PARAGRAPH 204 | Eu tentei traçar um paralelo entre os conceitos de programação 205 | com os conceitos que um novo programador já possui; 206 | para apresentar as idéias de uma maneira que o entendimento seja 207 | intuitivo, ao invés do tutorial despejar apenas informações. 208 | Programação Orientada a Objetos faz isso, por si só, muito bem. 209 | Eu fui capaz de me referir a "objetos" e diferentes "tipos de objetos" 210 | muito rapidamente nesse tutorial, soltando tais informações nos mais 211 | inocentes momentos. Eu não falei nada do tipo "tudo em Ruby é um objeto" 212 | ou "números e strings são tipos de objetos", porque essas 213 | coisas não dizem nada para um novo programador. Ao invés disso, 214 | eu vou falar sobre strings (e não sobre "objetos do tipo string"), 215 | e algumas vezes eu vou me referir a "objetos", apenas no sentido de "as coisas 216 | nesses programas". O fato de que todas essas coisas em Ruby são 217 | objetos fez com que esse tipo de inconsistência da minha parte funcionasse tão bem. 218 | END_PARAGRAPH 219 | end 220 | para do <<-END_PARAGRAPH 221 | Sobretudo, eu procurei fugir do jargão desnecessário da 222 | OO, eu procurei ter certeza de que, se eles têm de aprender 223 | uma palavra, que aprendam a certa (Eu não quero que eles 224 | tenham de aprender em duplicidade, certo?). Então, eu chamei 225 | tudo de "strings", e não "texto". Métodos precisam ser chamados 226 | de alguma coisa, então eu os chamei de métodos. 227 | END_PARAGRAPH 228 | end 229 | para do <<-END_PARAGRAPH 230 | A medida que os exercícios foram sendo concebidos, eu achei 231 | que estava com bons exercícios, mas você nunca pode colocar 232 | exercícios demais. Honestamente, eu acho que eu gastei quase 233 | metade do meu tempo apenas tentando fazer exercícios divertidos 234 | e interessantes. Exercícios entediantes apenas aniquilam qualquer 235 | desejo de programar, enquanto que o exercício perfeito cria 236 | aquela coceira no programador novo que ele não consegue ficar sem 237 | coçar. Resumindo, não gaste muito tempo tentando fazer exercícios bons. 238 | END_PARAGRAPH 239 | end 240 | puts HLINE 241 | h2 { 'Sobre o Tutorial Original' } 242 | para do <<-END_PARAGRAPH 243 | As páginas do tutorial (esta página, inclusive) são geradas por um 244 | grande programa em Ruby, 245 | claro. :-) 246 | Assim, elas possuem recursos elegantes. Por exemplo, todos os 247 | exemplos de código são realmente executados toda vez que você 248 | vê a página, e a saída dos mesmos é a saída que eles geram. 249 | Eu acredito que essa é a maneira mais fácil, melhor e, certamente, a 250 | mais legal de ter certeza que todo o código mostrado 251 | funciona exatamente como eu digo que funciona. 252 | Você não precisa se preocupar com a possibilidade de eu ter copiado 253 | a saída de um exemplo erroneamente ou esquecido de testar um código: 254 | tudo é testado na hora que você vê. Então, na seção de geradores de 255 | números aleatórios, você vai ver que os números mudam sempre... lindo. 256 | (Eu usei um truque parecido na hora de escrever o livro, mas é óbvio que isso 257 | é muito mais aparente aqui no tutorial.) 258 | END_PARAGRAPH 259 | end 260 | h2 { "Sobre o Material Traduzido" } 261 | para do <<-END_PARAGRAPH 262 | O código original descrito por Chris Pine acima, era uma versão simples e implementada sobre 263 | CGI. Em total ritmo de 2008, eu mesmo (Fabio Akita) modifiquei esse código. Sem muitas 264 | modificações sobre o original, transportei o código para rodar sobre Rails 2.0.2. 265 | END_PARAGRAPH 266 | end 267 | 268 | para do <<-END_PARAGRAPH 269 | Esse código está todo disponível no GitHub, neste endereço: 270 | END_PARAGRAPH 271 | end 272 | 273 | para do <<-END_PARAGRAPH 274 | https://github.com/jmonteiro/aprendaaprogramar 275 | END_PARAGRAPH 276 | end 277 | 278 | para do <<-END_PARAGRAPH 279 | Por motivos de performance, os códigos (que localmente são realmente executados em tempo real 280 | conforme Chris explicou) não são executados online, sendo uma cópia estática. Para ter todos os 281 | benefícios do programa em tempo real, baixe o código para rodar sobre Rails. 282 | END_PARAGRAPH 283 | end 284 | para do 285 | ''+ 286 | 'powered by Ruby'+ 287 | '' 288 | end 289 | puts HLINE 290 | h2 { 'Agradecimentos' } 291 | para do <<-END_PARAGRAPH 292 | Finalizando, eu gostaria de agradecer a todos da lista ruby-talk 293 | por suas idéis e pelo encorajamento, aos meus maravilhosos 294 | revisores, por sua ajuda em fazer o livro muito melhor do que 295 | eu poderia fazer sozinho, especialmente à minha querida esposa, 296 | por ser minha principal revisora/testadora/cobaia/musa, ao Matz, 297 | por ter criado essa fabulosa linguagem, e aos Pragmatic Programmers, por 298 | me falar sobre a linguagem—e, é claro, por publicar meu livro! 299 | END_PARAGRAPH 300 | end 301 | para do <<-END_PARAGRAPH 302 | Se você notar qualquer erro ou falha de digitação, se tiver 303 | qualquer comentário ou sugestão, ou um bom exercício que eu possa 304 | incluir, por favor me avise (se você falar 305 | inglês) ou, se preferir falar em português, 306 | avise o Júlio Monteiro. 307 | END_PARAGRAPH 308 | end 309 | end 310 | 311 | puts HLINE 312 | para(:style=>'padding-bottom: 20px;') { "© 2003-#{Time.now.year} Chris Pine" } 313 | end # contentPane 314 | end # pageWidth 315 | end # body 316 | end # html 317 | end 318 | end 319 | -------------------------------------------------------------------------------- /lib/learn_to_program_tutorial/menu.rb: -------------------------------------------------------------------------------- 1 | module Menu 2 | # menu helpers 3 | 4 | def menuBookLink 5 | para(:class=>'funnyMenuText fancyMenuText', :style=>'font-size: 12px; font-family: times, serif;') { 'a versão' } 6 | para(:class=>'funnyMenuText fancyMenuText', :style=>'font-size: 12px; font-family: times, serif;') { 'melhorada' } 7 | para(:class=>'funnyMenuText fancyMenuText', :style=>'font-size: 12px; font-family: times, serif; letter-spacing: 6px; font-variant: small-caps;') { 'estendida' } 8 | puts "" 9 | img(:width=>'100', :height=>'120', :src=>'images/LTP_cover.jpg') 10 | puts '' 11 | end 12 | 13 | def menuTOC 14 | para(:class=>'funnyMenuText') { '« o tutorial original »' } 15 | 16 | ol(:start=>'0', :style=>'padding-top: 15px; padding-bottom: 15px;') do 17 | @chapters.sort_by{|x| x[0]}.each do |aChapNum, aChapter| 18 | if aChapNum != 'format' 19 | li { makeLink(aChapter[0],aChapter[1]) } 20 | end 21 | end 22 | end 23 | 24 | para do <<-END_PARAGRAPH 25 | (Versão Original 26 | por Chris Pine.) 27 | END_PARAGRAPH 28 | end 29 | para do <<-END_PARAGRAPH 30 | (Tradução em Japonês 31 | por Shin Nishiyama.) 32 | END_PARAGRAPH 33 | end 34 | para do <<-END_PARAGRAPH 35 | (Tradução em Francês 36 | por Jean‑Pierre ANGHEL.) 37 | END_PARAGRAPH 38 | end 39 | para do <<-END_PARAGRAPH 40 | (Tradução em Russo 41 | por Mikhail Shokhirev.) 42 | END_PARAGRAPH 43 | end 44 | para do <<-END_PARAGRAPH 45 | (Tradução em Dinamarquês 46 | por Gunner Carstens.) 47 | END_PARAGRAPH 48 | end 49 | para do <<-END_PARAGRAPH 50 | (Tradução em Bósnio 51 | por Rusmir Gadžo.) 52 | END_PARAGRAPH 53 | end 54 | end 55 | end -------------------------------------------------------------------------------- /lib/learn_to_program_tutorial/methods.rb: -------------------------------------------------------------------------------- 1 | module Methods 2 | # 3 | # METHODS 4 | # 5 | 6 | def generateMethods 7 | para do <<-END_PARAGRAPH 8 | Até agora nós vimos uma porção de métodos diferentes, 9 | #{code 'puts'} e #{code 'gets'} 10 | dentre outros (Teste Surpresa: Liste todos 11 | os métodos que vimos até agora! 12 | Foram dez deles; a resposta está mais embaixo.), 13 | mas nós não conversamos realmente sobre o que são métodos. 14 | Nós sabemos o que eles fazem, mas não sabemos o que eles são. 15 | END_PARAGRAPH 16 | end 17 | para do <<-END_PARAGRAPH 18 | Mas, na verdade, isso é o que eles são: coisas 19 | que fazem coisas. Se objetos (como strings, 20 | inteiros e floats) são os substantivos na linguagem Ruby, 21 | os métodos são como os verbos. 22 | E, ao contrário do Português (em que há sujeitos indefinidos 23 | e outras construções esotéricas), você não pode ter um 24 | verbo sem um substantivo para executar o verbo. Mas mesmo 25 | o Português trata a ausência de um substantivo como exceção: 26 | por exemplo, contar o tempo não é algo que simplesmente acontece; 27 | um relógio (ou cronômetro, ou algo parecido) deve fazê-lo. Em 28 | Português diríamos: "O relógio conta o tempo". Em Ruby dizemos 29 | #{code 'relogio.tiquetaque'} (presumindo que #{code 'relogio'} 30 | é um objeto Ruby, claro). 31 | Programadores podem dizer que estamos "chamando o método 32 | #{code 'tiquetaque'} do #{code 'relogio'}," 33 | ou que "chamamos #{code 'tiquetaque'} no #{code 'relogio'}." 34 | END_PARAGRAPH 35 | end 36 | para do <<-END_PARAGRAPH 37 | E então, você respondeu o quiz? Ótimo. Bem, tenho 38 | certeza que você lembrou dos métodos 39 | #{code 'puts'}, #{code 'gets'} e #{code 'chomp'}, 40 | que acabamos de ver. Você também provavelmente 41 | lembrou dos métodos de conversão, 42 | #{code 'to_i'}, #{code 'to_f'} 43 | e #{code 'to_s'}. No entanto, você descobriu os 44 | outros quatro? Pois não eram ninguém menos 45 | que nossos velhos amigos da matemática, #{code '+'}, 46 | #{code '-'}, #{code '*'} e #{code '/'}! 47 | END_PARAGRAPH 48 | end 49 | para do <<-END_PARAGRAPH 50 | Como eu estava dizendo, todo método precisa de um objeto. 51 | Geralmente é fácil dizer qual objeto está executando o 52 | método: é aquilo que vem logo antes do ponto, como 53 | no nosso exemplo do #{code 'relogio.tiquetaque'}, ou em 54 | #{code '101.to_s'}. 55 | Às vezes, no entanto, isso não é tão óbvio; como com os 56 | métodos aritméticos. A bem da verdade, 57 | #{code '5 + 5'} é realmente apenas um atalho para se 58 | escrever #{code '5.+ 5'}. 59 | Por exemplo: 60 | END_PARAGRAPH 61 | end 62 | prog do <<-END_CODE 63 | puts 'olá '.+ 'mundo' 64 | puts (10.* 9).+ 9 65 | END_CODE 66 | end 67 | para do <<-END_PARAGRAPH 68 | Não é muito bonito, então nós nunca mais vamos escrever desse jeito; 69 | no entanto, é importante entender o que realmente está 70 | acontecendo. 71 | (Na minha máquina, isso também me dá um aviso: 72 | #{output 'warning: parenthesize argument(s) for future version'}. 73 | O código ainda rodou sem problemas, mas ele está me dizendo que está com 74 | problemas para descobrir o que eu quis dizer, e pedindo para usar mais parênteses no 75 | futuro). 76 | Isso também nos dá um entendimento mais profundo sobre por que 77 | podemos fazer #{code "'porco'*5"} mas não #{code "5*'porco'"}: 78 | #{code "'porco'*5"} está dizendo ao #{code "'porco'"} para se 79 | multiplicar, mas #{code "5*'porco'"} está pedindo ao #{code '5'} 80 | que se multiplique. #{code "'porco'"} sabe como fazer 81 | #{code '5'} cópias de si mesmo e juntá-las; no entanto, #{code '5'} 82 | vai ter muito mais dificuldade para fazer 83 | #{code "'porco'"} cópias de si mesmo e juntá-las. 84 | END_PARAGRAPH 85 | end 86 | para do <<-END_PARAGRAPH 87 | E, claro, nós ainda temos o #{code 'puts'} 88 | e o #{code 'gets'} para explicar. Onde estão seus 89 | objetos? Em Português, você pode às vezes omitir o 90 | substantivo; por exemplo, se um vilão grita "Morra!", 91 | o substantivo implícito é a pessoa com quem ele está 92 | gritando. Em Ruby, se dissermos 93 | #{code "puts 'ser ou não ser'"}, o que 94 | eu realmente estou dizendo é 95 | #{code "self.puts 'ser ou não ser'"}. 96 | Então o que é #{code 'self'}? É uma variável especial 97 | que aponta para o objeto onde você está. 98 | Nós nem sabemos como estar em um 99 | objeto ainda, mas até descobrirmos, nós 100 | estaremos sempre em um grande objeto que é... 101 | o programa inteiro! E para nossa sorte, o 102 | programa tem alguns métodos próprios, como 103 | #{code 'puts'} e #{code 'gets'}. 104 | Preste atenção: 105 | END_PARAGRAPH 106 | end 107 | prog do <<-END_CODE 108 | naoAcreditoQueFizUmNomeDeVariavelTaoGrandeApenasParaGuardarUm3 = 3 109 | puts naoAcreditoQueFizUmNomeDeVariavelTaoGrandeApenasParaGuardarUm3 110 | self.puts naoAcreditoQueFizUmNomeDeVariavelTaoGrandeApenasParaGuardarUm3 111 | END_CODE 112 | end 113 | para do <<-END_PARAGRAPH 114 | Se você não acompanhou tudo o que aconteceu, não tem problema. 115 | A coisa importante para aprender disso tudo é que cada 116 | métodos está sendo executado pelo mesmo objeto, mesmo 117 | que ele não esteja na sua frente. Se você entender isso, então 118 | está preparado. 119 | END_PARAGRAPH 120 | end 121 | h2 {'Métodos Elegantes da String'} 122 | para do <<-END_PARAGRAPH 123 | Vamos aprender alguns métodos divertidos da string. 124 | Você não precisa memorizar todos eles; você pode 125 | apenas olhar esta página novamente se esquecê-los. 126 | Eu só quero mostrar uma pequena parte do que 127 | as strings podem fazer. Na verdade, eu mesmo não lembro 128 | da metade dos métodos da string—mas não tem 129 | problema, pois existem ótimas referências na internet 130 | com todos os métodos da string listados e explicados. 131 | (Vou mostrar onde encontrá-los no final deste tutorial.) 132 | Pra falar a verdade, eu nem quero saber todos 133 | os métodos da string; é como saber todas as palavras do 134 | dicionário. Eu posso falar Português muito bem sem saber 135 | todas as palavras do dicionário... e esse não é exatamente 136 | o seu propósito? Para que você não precise 137 | saber tudo que está nele? 138 | END_PARAGRAPH 139 | end 140 | para do <<-END_PARAGRAPH 141 | Então, nosso primeiro método da string é o #{code 'reverse'}, 142 | que nos dá uma versão ao contrário da string: 143 | END_PARAGRAPH 144 | end 145 | prog do <<-END_CODE 146 | var1 = 'pare' 147 | var2 = 'radar' 148 | var3 = 'Voce consegue pronunciar esta frase ao contrario?' 149 | 150 | puts var1.reverse 151 | puts var2.reverse 152 | puts var3.reverse 153 | puts var1 154 | puts var2 155 | puts var3 156 | END_CODE 157 | end 158 | para do <<-END_PARAGRAPH 159 | Como você pode ver, #{code 'reverse'} não inverte a 160 | string original; ela apenas faz uma nova versão ao contrário dela. 161 | É por isso que #{code 'var1'} ainda é #{code "'pare'"} 162 | mesmo após a chamada a #{code 'reverse'} em #{code 'var1'}. 163 | END_PARAGRAPH 164 | end 165 | para do <<-END_PARAGRAPH 166 | Outro método da string é #{code 'length'}, que nos diz 167 | o número de caracteres (incluindo espaços) na string: 168 | END_PARAGRAPH 169 | end 170 | prog ['Christopher David Pine'] do <<-END_CODE 171 | puts 'Qual o seu nome completo?' 172 | nome = gets.chomp 173 | puts 'Você sabia que seu nome possui ' + nome.length + ' caracteres, ' + nome + '?' 174 | END_CODE 175 | end 176 | para do <<-END_PARAGRAPH 177 | Uh-oh! Algo deu errado, e parece que isso aconteceu após a linha 178 | #{code 'nome = gets.chomp'}... Você enxerga o problema? Veja se consegue descobrir. 179 | END_PARAGRAPH 180 | end 181 | para do <<-END_PARAGRAPH 182 | O problema está em #{code 'length'}: ele lhe dá um número, mas queremos uma string. 183 | Fácil, vamos colocar um #{code 'to_s'} (e cruzar os dedos): 184 | END_PARAGRAPH 185 | end 186 | prog ['Christopher David Pine'] do <<-END_CODE 187 | puts 'Qual o seu nome completo?' 188 | nome = gets.chomp 189 | puts 'Você sabia que seu nome possui ' + nome.length.to_s + ' caracteres, ' + nome + '?' 190 | END_CODE 191 | end 192 | para do <<-END_PARAGRAPH 193 | Não, eu não sabia disso. Nota: este é o número de 194 | caracteres no meu nome, não o número de letras 195 | (conte-as). Eu acho que conseguimos escrever um programa que 196 | pergunta seu primeiro nome, nome do meio e sobrenome individualmente e 197 | some todos os tamanhos... Ei, por que você não faz isso? Vá em frente, 198 | eu espero. 199 | END_PARAGRAPH 200 | end 201 | para do <<-END_PARAGRAPH 202 | Pronto? Bom! É um programa legal, não é? 203 | Depois de mais uns capítulos, entretanto, você vai ficar maravilhado com 204 | o que conseguirá fazer. 205 | END_PARAGRAPH 206 | end 207 | para do <<-END_PARAGRAPH 208 | Existem alguns métodos da string que conseguem mudar a caixa (maiúsculas 209 | e minúsculas) da sua string. #{code 'upcase'} muda todas as letras minúsculas 210 | para maiúsculas, e #{code 'downcase'} muda todas as letras maiúsculas para 211 | minúsculas. #{code 'swapcase'} troca a caixa de todas as letras da string e, 212 | finalmente, #{code 'capitalize'} é parecido com #{code 'downcase'}, exceto que 213 | ele troca o primeiro caractere para maiúsculo (se for uma letra). 214 | END_PARAGRAPH 215 | end 216 | prog do <<-END_CODE 217 | letras = 'aAbBcCdDeE' 218 | puts letras.upcase 219 | puts letras.downcase 220 | puts letras.swapcase 221 | puts letras.capitalize 222 | puts ' a'.capitalize 223 | puts letras 224 | END_CODE 225 | end 226 | para do <<-END_PARAGRAPH 227 | Coisas bem simples. Como você pode ver na linha 228 | #{code "puts ' a'.capitalize"}, o método #{code 'capitalize'} 229 | apenas deixa em maiúsculo o primeiro caractere, não a primeira 230 | letra. Também, como vimos anteriormente, durante todas essas chamadas 231 | de métodos, #{code 'letras'} continuou inalterada. Eu não quero me alongar nesse 232 | ponto, mas é importante entender. Existem alguns métodos que mudam o 233 | objeto associado, mas ainda não vimos nenhum, e nem iremos ver durante algum tempo. 234 | END_PARAGRAPH 235 | end 236 | para do <<-END_PARAGRAPH 237 | O último método elegante da string que iremos ver é 238 | para formatação visual. 239 | O primeiro, #{code 'center'}, adiciona espaços no começo e no 240 | fim da string para torná-la centralizada. No entanto, assim como 241 | você precisa dizer ao #{code 'puts'} o que quer que seja impresso, e ao 242 | #{code '+'} o que quer que seja adicionado, você precisa dizer ao 243 | #{code 'center'} a largura total da string a ser centralizada. Então 244 | se eu quiser centralizar as linhas de um poema, eu faria assim: 245 | END_PARAGRAPH 246 | end 247 | prog do <<-END_CODE 248 | larguraDaLinha = 50 249 | puts( 'Old Mother Hubbard'.center(larguraDaLinha)) 250 | puts( 'Sat in her cupboard'.center(larguraDaLinha)) 251 | puts( 'Eating her curds an whey,'.center(larguraDaLinha)) 252 | puts( 'When along came a spider'.center(larguraDaLinha)) 253 | puts( 'Which sat down beside her'.center(larguraDaLinha)) 254 | puts('And scared her poor shoe dog away.'.center(larguraDaLinha)) 255 | END_CODE 256 | end 257 | para do <<-END_PARAGRAPH 258 | Hum... Eu não acho que essa rima é assim, mas sou muito preguiçoso 259 | para procurar. (Também, eu queria alinhar a parte do 260 | #{code '.center larguraDaLinha'}, por isso acrescentei espaços extra antes 261 | das strings. Isso é só por que acho que fica mais bonito assim. 262 | Programadores geralmente têm opiniões fortes sobre o que é 263 | bonito num programa, e eles geralmente discordam sobre o assunto. 264 | Quanto mais você programar, mais vai descobrir seu próprio estilo). 265 | Falando em ser preguiçoso, a preguiça nem sempre é algo ruim na programação. 266 | Por exemplo, viu como eu guardei a largura do poema numa variável 267 | #{code 'larguraDaLinha'}? Fiz isso pois se quiser tornar o poema mais 268 | largo mais tarde, só precisarei mudar a primeira linha do programa, 269 | ao invés de todas as linhas que são centralizadas. Com um poema muito 270 | longo, isso poderia me poupar um bom tempo. Esse tipo de preguiça é na 271 | verdade uma virtude na programação. 272 | END_PARAGRAPH 273 | end 274 | para do <<-END_PARAGRAPH 275 | Então, em relação à centralização... você deve ter percebido que não está 276 | tão bonito quanto um processador de texto teria feito. Se você realmente 277 | quer centralização perfeita (e talvez uma fonte melhor), então você 278 | deveria apenas usar um processador de texto! Ruby é uma ferramenta 279 | maravilhosa, mas nenhuma ferramenta é a ferramenta certa para 280 | qualquer trabalho. 281 | END_PARAGRAPH 282 | end 283 | para do <<-END_PARAGRAPH 284 | Os outros dois métodos de formatação da string são #{code 'ljust'} e 285 | #{code 'rjust'}, que fazem o texto justificado à esquerda e 286 | justificado à direita. Eles são parecidos com o #{code 'center'}, 287 | exceto que eliminam os espaços em branco da string do lado direito e esquerdo, 288 | respectivamente. Vamos ver os três em ação: 289 | END_PARAGRAPH 290 | end 291 | prog do <<-END_CODE 292 | larguraDaLinha = 40 293 | str = '--> text <--' 294 | puts str.ljust larguraDaLinha 295 | puts str.center larguraDaLinha 296 | puts str.rjust larguraDaLinha 297 | puts str.ljust (larguraDaLinha/2) + str.rjust (larguraDaLinha/2) 298 | END_CODE 299 | end 300 | h2 {'Umas Coisinhas Para Tentar'} 301 | para do <<-END_PARAGRAPH 302 | • Escreva um programa do Chefe Zangado. Ele deve perguntar o que você quer de forma rude. 303 | Qualquer que seja a sua resposta, o Chefe Zangado vai gritar de volta para você, e então 304 | despedi-lo. Por exemplo, se você digitar #{input 'Eu quero um aumento.'}, ele deve gritar 305 | de volta #{output 'O QUE VOCÊ QUER DIZER COM "EU QUERO UM AUMENTO."?!? VOCÊ ESTÁ DESPEDIDO!!'} 306 | END_PARAGRAPH 307 | end 308 | para do <<-END_PARAGRAPH 309 | • Eis aqui algo para você fazer para brincar um pouco mais com 310 | #{code 'center'}, #{code 'ljust'} e #{code 'rjust'}: Escreva um programa 311 | que irá mostrar um Índice de forma que fique parecido com: 312 | END_PARAGRAPH 313 | end 314 | puts '
' +
315 |           '                Tabela de Conteúdo                ' + $/ +
316 |           '                                                  ' + $/ +
317 |           'Capítulo 1:  Números                      página 1' + $/ +
318 |           'Capítulo 2:  Letras                      página 72' + $/ +
319 |           'Capítulo 3:  Variáveis                  página 118' + $/ +
320 |           '
' 321 | h2 {'Matemática Avançada'} 322 | para do <<-END_PARAGRAPH 323 | (Esta seção é totalmente opcional. Ela assume um certo nível 324 | de conhecimento matemático. Se você não estiver interessado, você pode 325 | ir direto para o #{makeLink 'Controle de Fluxo', :generateFlowControl} 326 | sem nenhum problema. No entanto, uma breve passada pela seção de 327 | Números Aleatórios pode ser útil.) 328 | END_PARAGRAPH 329 | end 330 | para do <<-END_PARAGRAPH 331 | Não há tantos métodos nos números quanto nas strings 332 | (apesar de eu ainda não ter decorado todos). Aqui, iremos olhar o 333 | resto dos métodos de aritmética, um gerador de números aleatórios e 334 | o objeto #{code 'Math'}, com seus métodos trigonométricos e 335 | transcendentais. 336 | END_PARAGRAPH 337 | end 338 | h2 {'Mais Aritimética'} 339 | para do <<-END_PARAGRAPH 340 | Os outros dois métodos aritméticos são #{code '**'} (exponenciação) 341 | e #{code '%'} (módulo). Então se você quisesse dizer "cinco ao quadrado" 342 | em Ruby, você escreveria #{code '5**2'}. Você também pode usar 343 | floats para seu expoente, então se você quiser a raiz quadrada de 5, 344 | você pode escrever #{code '5**0.5'}. O método módulo lhe dá o resto da 345 | divisão por um número. Então, por exemplo, se eu divido 7 por 3, 346 | eu tenho 2 com resto 1. Vamos vê-los em ação num programa: 347 | END_PARAGRAPH 348 | end 349 | prog do <<-END_CODE 350 | puts 5**2 351 | puts 5**0.5 352 | puts 7/3 353 | puts 7%3 354 | puts 365%7 355 | END_CODE 356 | end 357 | para do <<-END_PARAGRAPH 358 | Pela última linha, aprendemos que um ano (não-bissexto) tem um certo 359 | número de semanas, mais um dia. Então se seu aniversário caiu numa 360 | terça-feira este ano, ele será numa quarta-feira no ano que vem. 361 | Você também pode usar floats com o método módulo. Basicamente, ele 362 | funciona da única maneira razoável que consegue... Mas eu vou deixar 363 | você brincar um pouco com isso. 364 | END_PARAGRAPH 365 | end 366 | para do <<-END_PARAGRAPH 367 | Tem um último método para ser mencionado antes de vermos o gerador de 368 | números aleatórios: #{code 'abs'}. Ele simplesmente pega o valor 369 | absoluto de um número: 370 | END_PARAGRAPH 371 | end 372 | prog do <<-END_CODE 373 | puts((5-2).abs) 374 | puts((2-5).abs) 375 | END_CODE 376 | end 377 | h2 {'Números Aleatórios'} 378 | para do <<-END_PARAGRAPH 379 | Ruby vem com um gerador de números aleatórios bem legal. O método que 380 | escolhe aleatoriamente um número é o #{code 'rand'}. Se você chamar #{code 'rand'} 381 | simplesmente assim, você vai ter um float maior ou igual a #{code '0.0'} e menor 382 | que #{code '1.0'}. Se você der um inteiro (#{code '5'} por exemplo) para o #{code 'rand'}, 383 | ele vai te dar um inteiro maior ou igual a #{code '0'} e menor que #{code '5'} (então são 384 | cinco números possíveis, de #{code '0'} até #{code '4'}). 385 | END_PARAGRAPH 386 | end 387 | para do <<-END_PARAGRAPH 388 | Vamos ver o #{code 'rand'} em ação. (Se você recarregar esta página, estes números vão 389 | mudar a cada vez. Você sabia que eu estou realmente rodando estes programas, não sabia?) 390 | END_PARAGRAPH 391 | end 392 | prog do <<-END_CODE 393 | puts rand 394 | puts rand 395 | puts rand 396 | puts(rand(100)) 397 | puts(rand(100)) 398 | puts(rand(100)) 399 | puts(rand(1)) 400 | puts(rand(1)) 401 | puts(rand(1)) 402 | puts(rand(99999999999999999999999999999999999999999999999999999999999)) 403 | puts('O homem do tempo disse que existe '+rand(101).to_s+'% de chance de chover,') 404 | puts('mas você não pode nunca confiar num homem do tempo.') 405 | END_CODE 406 | end 407 | para do <<-END_PARAGRAPH 408 | Perceba que eu usei #{code 'rand(101)'} para conseguir os números de #{code '0'} 409 | até #{code '100'}, e que #{code 'rand(1)'} sempre retorna #{code '0'}. Não entender o 410 | intervalo dos possíveis valores retornados é o maior erro que eu vejo as pessoas 411 | cometerem ao usar #{code 'rand'}; mesmo programadores profissionais; mesmo em 412 | produtos terminados que você pode comprar na loja. Eu inclusive tive um tocador de CD 413 | que, se configurado para "Tocar Aleatoriamente", iria tocar todas as músicas menos 414 | a última... (Eu imagino o que aconteceria se eu colocasse um CD com apenas uma música 415 | nele?) 416 | END_PARAGRAPH 417 | end 418 | para do <<-END_PARAGRAPH 419 | As vezes você pode querer que #{code 'rand'} retorne os mesmos números aleatórios 420 | na mesma sequência em duas execuções diferentes do seu programa. (Por exemplo, uma vez eu 421 | estava usando números aleatórios gerados para criar um mundo gerado aleatoriamente num 422 | jogo de computador. Se eu encontrasse um mundo que eu realmente gostasse, talvez eu quisesse 423 | jogar nele novamente, ou mandá-lo para um amigo). Para isso, você precisa configurar 424 | a semente, que você consegue fazer com #{code 'srand'}. Desta forma: 425 | END_PARAGRAPH 426 | end 427 | prog do <<-END_CODE 428 | srand 1776 429 | puts(rand(100)) 430 | puts(rand(100)) 431 | puts(rand(100)) 432 | puts(rand(100)) 433 | puts(rand(100)) 434 | puts '' 435 | srand 1776 436 | puts(rand(100)) 437 | puts(rand(100)) 438 | puts(rand(100)) 439 | puts(rand(100)) 440 | puts(rand(100)) 441 | END_CODE 442 | end 443 | para do <<-END_PARAGRAPH 444 | Ele fará a mesma coisa sempre que você alimentá-lo com a mesma semente. Se você quer 445 | voltar a ter números diferentes (como acontece quando você nunca usa 446 | #{code 'srand'}), então apenas chame #{code 'srand 0'}. Isso alimenta o gerador com 447 | um número realmente estranho, usando (dentre outras coisas) a hora atual do seu 448 | computador, com precisão de milisegundos. 449 | END_PARAGRAPH 450 | end 451 | h2 {"O Objeto #{code 'Math'}"} 452 | para do <<-END_PARAGRAPH 453 | Finalmente, vamos olhar para o objeto #{code 'Math'}. Vamos começar de uma vez: 454 | END_PARAGRAPH 455 | end 456 | prog do <<-END_CODE 457 | puts(Math::PI) 458 | puts(Math::E) 459 | puts(Math.cos(Math::PI/3)) 460 | puts(Math.tan(Math::PI/4)) 461 | puts(Math.log(Math::E**2)) 462 | puts((1 + Math.sqrt(5))/2) 463 | END_CODE 464 | end 465 | para do <<-END_PARAGRAPH 466 | A primeira coisa que você percebeu foi provavelmente a notação do #{code '::'}. Explicar 467 | o operador de escopo (que é o que ele é) está um pouco além do, uh... escopo 468 | deste tutorial. Não é nenhum trocadilho. Eu juro. Basta dizer que você pode usar 469 | #{code 'Math::PI'} exatamente da forma como você espera. 470 | END_PARAGRAPH 471 | end 472 | para do <<-END_PARAGRAPH 473 | Como você pode ver, #{code 'Math'} tem todas as coisas que você esperaria que 474 | uma calculadora científica decente tivesse. E, como sempre, os floats estão 475 | realmente perto de serem as respostas certas. 476 | END_PARAGRAPH 477 | end 478 | para do <<-END_PARAGRAPH 479 | Então vamos entrar no #{makeLink 'fluxo', :generateFlowControl}! 480 | END_PARAGRAPH 481 | end 482 | end 483 | end 484 | -------------------------------------------------------------------------------- /lib/learn_to_program_tutorial/numbers.rb: -------------------------------------------------------------------------------- 1 | module Numbers 2 | # 3 | # NUMBERS 4 | # 5 | 6 | def generateNumbers 7 | para do <<-END_PARAGRAPH 8 | Agora que você já #{makeLink('arranjou', :generateSetup)} 9 | tudo, vamos escrever um programa! Abra seu editor de texto 10 | favorito e digite o seguinte: 11 | END_PARAGRAPH 12 | end 13 | prog false do <<-END_CODE 14 | puts 1+2 15 | END_CODE 16 | end 17 | para do <<-END_PARAGRAPH 18 | Salve seu programa (sim, isso é um programa!) como #{input 'calc.rb'} 19 | (o .rb é o que normalmente colocamos no final de 20 | programas escritos em Ruby). Agora rode o seu programa digitando 21 | #{input 'ruby calc.rb'} na linha de comando. Ele deve ter posto 22 | #{output '3'} na sua tela. Viu como programar não é tão difícil? 23 | END_PARAGRAPH 24 | end 25 | h2 {'Introdução ao '+(code 'puts')} 26 | para do <<-END_PARAGRAPH 27 | O que é então que está acontecendo no programa? Tenho certeza que você 28 | é capaz de adivinhar o quê #{code '1+2'} faz; nosso programa é 29 | praticamente a mesma coisa que: 30 | END_PARAGRAPH 31 | end 32 | prog false do <<-END_CODE 33 | puts 3 34 | END_CODE 35 | end 36 | para do <<-END_PARAGRAPH 37 | #{code 'puts'} simplesmente escreve na tela tudo que 38 | vem depois dele. 39 | END_PARAGRAPH 40 | end 41 | h2 {'Inteiro e Float'} 42 | para do <<-END_PARAGRAPH 43 | Na maioria das linguagens de programação (e não é diferente no Ruby) 44 | números sem pontos decimais são chamados de inteiros, e 45 | números com pontos decimais normalmente são chamados de 46 | números de ponto-flutuante, 47 | ou mais singelamente, floats. 48 | END_PARAGRAPH 49 | end 50 | para do <<-END_PARAGRAPH 51 | Eis alguns inteiros: 52 | END_PARAGRAPH 53 | end 54 | prog false do <<-END_CODE 55 | 5 56 | -205 57 | 9999999999999999999999999 58 | 0 59 | END_CODE 60 | end 61 | para do <<-END_PARAGRAPH 62 | E aqui estão alguns floats: 63 | END_PARAGRAPH 64 | end 65 | prog false do <<-END_CODE 66 | 54.321 67 | 0.001 68 | -205.3884 69 | 0.0 70 | END_CODE 71 | end 72 | para do <<-END_PARAGRAPH 73 | Na prática, a maioria dos programas não usa floats; 74 | apenas inteiros. 75 | (Afinal, ninguém quer ler 7.4 emails, ou navegar 1.8 páginas, 76 | ou ouvir 5.24 músicas favoritas) 77 | Floats são usados mais freqüentemente para fins acadêmicos 78 | (experimentos de física e afins) e para gráficos 3D. 79 | Mesmo a maioria dos programas que lidam com dinheiro usam 80 | inteiros; eles só ficam contando as moedinhas! 81 | END_PARAGRAPH 82 | end 83 | h2 {'Aritmética Simples'} 84 | para do <<-END_PARAGRAPH 85 | Até agora, temos tudo que é necessário para uma calculadora simples. 86 | (Calculadoras sempre usam floats, então se você quer que seu 87 | computador aja como uma calculadora, você também deve usar floats.) 88 | Para adição e subtração, usamos + e -, como 89 | vimos. Para multiplicação, usamos *, e para divisão 90 | usamos /. A maioria dos teclados possui essas 91 | teclas no teclado numérico. Se você tem teclado menor ou um laptop, 92 | você pode usar Shift 8 e / (fica na mesma 93 | tecla que ?). Vamos tentar expandir um pouco nosso calc.rb. 94 | Digite o seguinte e depois rode. 95 | END_PARAGRAPH 96 | end 97 | prog [], 'Isto é o que o programa retorna:' do <<-END_CODE 98 | puts 1.0 + 2.0 99 | puts 2.0 * 3.0 100 | puts 5.0 - 8.0 101 | puts 9.0 / 2.0 102 | END_CODE 103 | end 104 | para do <<-END_PARAGRAPH 105 | (Os espaços no programa não são importantes; eles só deixam 106 | o código mais legível.) Bom, não foi lá muito surpreendente. 107 | Vamos tentar agora com inteiros. 108 | END_PARAGRAPH 109 | end 110 | prog [], 'Basicamente a mesma coisa, não é?' do <<-END_CODE 111 | puts 1+2 112 | puts 2*3 113 | puts 5-8 114 | puts 9/2 115 | END_CODE 116 | end 117 | para do <<-END_PARAGRAPH 118 | Ahn... tirando aquele último ali! 119 | Quando você faz aritmética com inteiros, você recebe respostas em 120 | inteiros. Quando seu computador não sabe dar a resposta "certa", ele 121 | sempre arredonda para baixo. (Claro, #{output '4'} é a 122 | resposta certa em aritmética de inteiros para #{code '9/2'}; só 123 | pode não ser o que você estava esperando.) 124 | END_PARAGRAPH 125 | end 126 | para do <<-END_PARAGRAPH 127 | Talvez você esteja se perguntado para que divisão de inteiros serve. 128 | Bem, vamos dizer que você vai ao cinema, mas só tem $ 9. Aqui em 129 | Portland, você pode ver um filme no Bagdad por 2 pilas. A quantos 130 | filmes você pode assistir lá? #{code '9/2'}... #{output '4'} filmes. 131 | 4.5 não é a resposta certa neste caso; eles não vão deixar 132 | você ver metade de um filme, ou metade de você ver um filme inteiro... 133 | algumas coisas não são divisíveis. 134 | END_PARAGRAPH 135 | end 136 | para do <<-END_PARAGRAPH 137 | Agora experimente com alguns programas seus! Se você quiser 138 | escrever expressões mais complexas, você pode usar parênteses. 139 | Por exemplo: 140 | END_PARAGRAPH 141 | end 142 | prog do <<-END_CODE 143 | puts 5 * (12-8) + -15 144 | puts 98 + (59872 / (13*8)) * -52 145 | END_CODE 146 | end 147 | h2 {'Umas Coisinhas Para Tentar'} 148 | para do 149 | puts 'Escreva um programa que lhe dê:' 150 | end 151 | ul do 152 | li {'quantas horas há em um ano?'} 153 | li {'quantos minutos há em uma década?'} 154 | li {'qual é a sua idade em segundos?'} 155 | li {'quantos chocolates você pretende comer na vida?
'+ 156 | 'Aviso: Esta parte do programa pode demorar um pouco para computar!'} 157 | end 158 | para do 159 | puts "Eis uma pergunta mais difícil:" 160 | end 161 | ul do 162 | li {"Se minha idade é de #{(Time.now - Time.mktime(1976,8,3)).to_i / 1000000} milhões de segundos, qual é minha idade em anos?"} 163 | end 164 | para do <<-END_PARAGRAPH 165 | Quando você cansar de brincar com números, vamos dar uma 166 | olhada em algumas #{makeLink('letras', :generateLetters)}. 167 | END_PARAGRAPH 168 | end 169 | end 170 | end 171 | -------------------------------------------------------------------------------- /lib/learn_to_program_tutorial/setup.rb: -------------------------------------------------------------------------------- 1 | module Setup 2 | # 3 | # SETUP 4 | # 5 | 6 | def generateSetup 7 | para do <<-END_PARAGRAPH 8 | Quando você programa um computador, você tem que "falar" em 9 | uma língua que o seu computador entenda: uma linguagem de 10 | programação. Existem muitas e muitas linguagens por aí, e muitas 11 | são excelentes. Neste tutorial eu escolhi usar a minha favorita, 12 | Ruby. 13 | END_PARAGRAPH 14 | end 15 | #para do <<-END_PARAGRAPH 16 | # When you program a computer, you have to "speak" in a 17 | # language your computer understands: a programming 18 | # language. There are lots and lots of different 19 | # languages out there, and many of them are excellent. 20 | # In this tutorial I chose to use my favorite 21 | # programming language, Ruby. 22 | # END_PARAGRAPH 23 | #end 24 | para do <<-END_PARAGRAPH 25 | Além de ser a minha favorita, Ruby também é a linguagem mais 26 | fácil que eu já vi (e eu já vi uma boa quantidade delas). Aliás, 27 | esta é a verdadeira razão pela qual estou escrevendo este tutorial: 28 | Eu não decidi escrever este tutorial e aí escolhi Ruby por ser minha 29 | favorita; ao invés disso, eu descobri que o Ruby era tão fácil que 30 | eu decidi que deveria haver um bom tutorial que a usasse voltado 31 | para iniciantes. 32 | Foi a simplicidade do Ruby que inspirou este tutorial, não o fato 33 | dela ser minha favorita. 34 | (Escrever um tutorial similar usando outra linguagem, C++ ou Java, teria 35 | tomado centenas e centenas de páginas.) Mas não pense que Ruby é 36 | uma linguagem para iniciantes só porque é fácil! Ela é uma linguagem 37 | poderosa, de nível profissional como poucas. 38 | END_PARAGRAPH 39 | end 40 | #para do <<-END_PARAGRAPH 41 | # Aside from being my favorite, 42 | # Ruby is also the easiest programming language I have seen 43 | # (and I've seen quite a few). In fact, that's the real 44 | # reason I'm writing this tutorial: I didn't decide to write 45 | # a tutorial, and then choose Ruby because it's my favorite; 46 | # instead, I found Ruby to be so easy that I decided there 47 | # really ought to be a good beginner's tutorial which uses 48 | # it. It's Ruby's simplicity which prompted this tutorial, 49 | # not the fact that it's my favorite. 50 | # (Writing a similar tutorial using 51 | # another language, like C++ or Java, would have required 52 | # hundreds and hundreds of pages.) But don't think that 53 | # Ruby is a beginner's language just because it is easy! 54 | # It is a powerful, professional-strength programming 55 | # language if ever there was one. 56 | # END_PARAGRAPH 57 | #end 58 | para do <<-END_PARAGRAPH 59 | Quando você escreve algo em uma linguagem humana, o que é escrito 60 | é chamado de texto. Quando você escreve algo em uma linguagem de 61 | computador, o que é escrito é chamado de código. Eu incluí 62 | vários exemplos de código Ruby por todo este tutorial, a maioria 63 | deles programas completos que você pode rodar no seu próprio 64 | computador. Para deixar o código mais legível, eu colori partes dele 65 | com cores diferentes. (Por exemplo, números estão sempre em 66 | #{NUMBER_COLOR}.) 67 | Qualquer coisa que você tiver que digitar estará sempre numa 68 | #{input INPUT_DESC}, e qualquer coisa que o programa imprimir 69 | estará em uma #{output OUTPUT_DESC}. 70 | END_PARAGRAPH 71 | end 72 | #para do <<-END_PARAGRAPH 73 | # When you write something in a human language, what is 74 | # written is called text. When you write something in a computer 75 | # language, what is written is called code. I 76 | # have included lots of examples of Ruby code throughout 77 | # this tutorial, most of them complete programs you can 78 | # run on your own computer. To make the code easier to 79 | # read, I have colored parts of the code different 80 | # colors. (For example, numbers are always 81 | # #{NUMBER_COLOR}.) 82 | # Anything you are supposed to type in will be in a 83 | # #{input INPUT_DESC}, and anything a program prints 84 | # out will be in a #{output OUTPUT_DESC}. 85 | # END_PARAGRAPH 86 | #end 87 | para do <<-END_PARAGRAPH 88 | Se você encontrar algo que não entende, ou se você tiver 89 | uma pergunta que não foi respondida, tome nota e continue a ler! 90 | É bem possível que a resposta venha em um capítulo mais adiante. 91 | Porém, se sua pergunta não for respondida até o último 92 | capítulo, eu lhe mostrarei onde você pode ir para perguntar. 93 | Existem muitas pessoas maravilhosas por aí mais que dispostas a 94 | ajudar; você só precisa saber onde elas estão. 95 | END_PARAGRAPH 96 | end 97 | #para do <<-END_PARAGRAPH 98 | # If you come across something you don't understand, or you 99 | # have a question which wasn't answered, write it down and 100 | # keep reading! It's quite possible that the answer will 101 | # come in a later chapter. However, if your question was 102 | # not answered by the last chapter, I will tell you where 103 | # you can go to ask it. There are lots of wonderful people 104 | # out there more than willing to help; you just need to know 105 | # where they are. 106 | # END_PARAGRAPH 107 | #end 108 | para do <<-END_PARAGRAPH 109 | Mas primeiro nós precisamos baixar e instalar o Ruby no nosso 110 | computador. 111 | END_PARAGRAPH 112 | end 113 | h2 {'Instalação no Windows'} 114 | para do <<-END_PARAGRAPH 115 | A instalação do Ruby no Windows é muito fácil. Primeiro, você 116 | precisa baixar o 117 | Instalador Ruby. 118 | Pode haver mais de versão para escolher; este tutorial 119 | usa a versão #{RUBY_VERSION}, então assegure-se de que o que você 120 | baixar seja ao menos tão recente quanto ela. (Eu pegaria a última versão 121 | disponível.) Então simplesmente rode o programa de instalação. 122 | Ele perguntará onde você gostaria de instalar o Ruby. A não ser que 123 | você tenha uma boa razão para não fazer isso, eu instalaria no lugar 124 | recomendado. 125 | END_PARAGRAPH 126 | end 127 | #h2 {'Windows Installation'} 128 | #para do <<-END_PARAGRAPH 129 | # The Windows installation of Ruby is a breeze. First, you 130 | # need to download the 131 | # Ruby installer. 132 | # There might be a couple of versions to choose from; this tutorial 133 | # is using version #{RUBY_VERSION}, so make sure what you download is at 134 | # least as recent as that. (I would just get the latest 135 | # version available.) Then simply run the installation program. 136 | # It will ask you where you want to install Ruby. Unless you have 137 | # a good reason for it, I would just install it in the default 138 | # location. 139 | # END_PARAGRAPH 140 | #end 141 | para do <<-END_PARAGRAPH 142 | Para programar, você precisa poder escrever programas e rodá-los. 143 | Para fazer isso, você vai precisar de um editor de texto e uma 144 | linha de comando. 145 | END_PARAGRAPH 146 | end ## linha de comando? 147 | 148 | #para do <<-END_PARAGRAPH 149 | #In order to program, you need to be able to write programs and 150 | #to run programs. To do this, you will need a text editor and a 151 | #command line. 152 | #END_PARAGRAPH 153 | #end 154 | para do <<-END_PARAGRAPH 155 | O instalador do Ruby vem com um editor de texto adorável chamado 156 | SciTE (the Scintilla Text Editor). Você pode rodar o SciTE 157 | selecionando-o no menu Iniciar. Se você quiser que o seu código 158 | seja colorido como os exemplos deste tutorial, baixe estes arquivos 159 | e coloque-os na sua pasta SciTE (c:/ruby/scite se você escolher 160 | o local recomendado). 161 | END_PARAGRAPH 162 | end 163 | #para do <<-END_PARAGRAPH 164 | # The Ruby installer comes with a lovely text editor called SciTE 165 | # (the Scintilla Text Editor). You can run SciTE by selecting it 166 | # from the start menu. If you would like your code to be colored 167 | # like the examples in this tutorial, download these files and 168 | # put them in your SciTE folder (c:/ruby/scite if you chose the 169 | # default location): 170 | # END_PARAGRAPH 171 | #end 172 | ul do 173 | li {'Propriedades Globais'} 174 | li {'Propriedades do Ruby'} 175 | end 176 | para do <<-END_PARAGRAPH 177 | Seria também uma boa idéia criar um diretório em algum lugar para manter 178 | todos os seus programas. Tenha certeza que, quando você salvar um 179 | programa, esteja salvando neste diretório. 180 | END_PARAGRAPH 181 | end 182 | para do <<-END_PARAGRAPH 183 | Para ir para sua linha de comando, selecione Prompt de Comando na pasta 184 | Acessórios do seu menu Iniciar. Você vai querer 185 | navegar para o diretório onde você mantém seus programas. 186 | Digitar #{input 'cd ..'} levará você para o diretório anterior, e 187 | #{input 'cd nome_do_diretorio'} colocará você dentro do diretório 188 | chamado nome_do_diretorio. Para ver todos seus diretórios 189 | dentro do diretório atual, digite #{input 'dir /ad'}. 190 | END_PARAGRAPH 191 | end 192 | para do <<-END_PARAGRAPH 193 | E é isto! Você está pronto para 194 | #{makeLink 'aprender a programar', :generateNumbers}. 195 | END_PARAGRAPH 196 | end 197 | h2 {'Instalação para Macintosh'} 198 | para do <<-END_PARAGRAPH 199 | Se você tiver um Mac OS X 10.2 (Jaguar), então você já tem 200 | Ruby no seu sistema! O que poderia ser mais fácil? 201 | Infelizmente, eu não acho que você possa usar Ruby no Mac OS X 10.1 202 | e versões anteriores. 203 | END_PARAGRAPH 204 | end 205 | para do <<-END_PARAGRAPH 206 | Para programar, você precisa ser capaz de escrever programas e 207 | executá-los. Para fazer isto, você precisará de um editor de textos e 208 | uma linha de comando. 209 | END_PARAGRAPH 210 | end 211 | para do <<-END_PARAGRAPH 212 | Sua linha de comando está acessível através da aplicação 213 | Terminal (encontrada em Aplicações/Utilitários). 214 | END_PARAGRAPH 215 | end 216 | para do <<-END_PARAGRAPH 217 | Para um editor de textos, você pode usar qualquer um com que você 218 | esteja familiarizado ou se sinta confortável usando. 219 | Se você usa TextEdit, entretanto, tenha certeza 220 | que você está salvando seus programas como somente-texto! Caso contrário seus programas 221 | não funcionarão. Outras opções para programar são 222 | emacs, vi, e pico, que estão todos acessíveis via 223 | linha de comando. 224 | END_PARAGRAPH 225 | end 226 | para do <<-END_PARAGRAPH 227 | E é isto! Você está pronto para 228 | #{makeLink 'aprender a programar', :generateNumbers}. 229 | END_PARAGRAPH 230 | end 231 | h2 {'Instalação em Linux'} 232 | para do <<-END_PARAGRAPH 233 | Primeiro, vale a pena checar se você já tem Ruby 234 | instalado. Digite #{input 'which ruby'}. Se este comando responder 235 | algo como #{output '/usr/bin/which: no ruby in (...)'}, então você precisa 236 | fazer o download do Ruby, 237 | caso contrário veja que versão do Ruby você possui com 238 | #{input 'ruby -v'}. Se for mais velha do que a última versão estável 239 | na página de download acima, pode ser bom atualizá-lo. 240 | END_PARAGRAPH 241 | end 242 | para do <<-END_PARAGRAPH 243 | Se você for o usuário root, então você provavelmente não precisa de 244 | qualquer instrução para instalar o Ruby. Se não for, você poderia 245 | pedir ao seu administrador de sistema para instalá-lo para você. 246 | (Desta forma todos neste sistema poderiam usar Ruby.) 247 | END_PARAGRAPH 248 | end 249 | para do <<-END_PARAGRAPH 250 | Caso contrário, você pode apenas instalá-lo de forma que apenas 251 | você possa usá-lo. 252 | Mova o arquivo baixado para um diretório temporário, como 253 | $HOME/tmp. Se o nome do arquivo for 254 | ruby-1.6.7.tar.gz, você pode abri-lo com 255 | #{input 'tar zxvf ruby-1.6.7.tar.gz'}. Mude do diretório atual 256 | para o diretório que acabou de ser criado (neste exemplo, 257 | #{input 'cd ruby-1.6.7'}). 258 | END_PARAGRAPH 259 | end 260 | para do <<-END_PARAGRAPH 261 | Configure sua instalação digitando 262 | #{input './configure --prefix=$HOME'}). Depois digite 263 | #{input 'make'}, que construirá seu interpretador Ruby. 264 | Isto pode levar alguns minutos. Após isto ter terminado, digite 265 | #{input 'make install'} para instalá-lo. 266 | END_PARAGRAPH 267 | end 268 | para do <<-END_PARAGRAPH 269 | Em seguida, você vai querer adicionar $HOME/bin para seu 270 | caminho de busca de comandos à variável de ambiente PATH, editando 271 | seu arquivo $HOME/.bashrc. 272 | (Você pode ter que se deslogar e logar novamente para que 273 | isto surta efeito.) Após ter feito isto, teste sua instalação: 274 | #{input 'ruby -v'}. Se mostrar a você qual a versão do Ruby que você 275 | tem, você pode agora remover os arquivos 276 | em $HOME/tmp (ou onde quer que você os colocou). 277 | END_PARAGRAPH 278 | end 279 | para do <<-END_PARAGRAPH 280 | E é isto! Você está pronto para 281 | #{makeLink 'aprender a programar', :generateNumbers}. 282 | END_PARAGRAPH 283 | end 284 | end 285 | end 286 | -------------------------------------------------------------------------------- /lib/learn_to_program_tutorial/variables.rb: -------------------------------------------------------------------------------- 1 | module Variables 2 | # 3 | # VARIABLES 4 | # 5 | 6 | def generateVariables 7 | para do <<-END_PARAGRAPH 8 | Até agora, sempre que usamos #{code 'puts'} numa string ou número, 9 | o que imprimimos some. O que eu quero dizer é, se quiséssemos imprimir 10 | algo duas vezes, teríamos que digitar duas vezes: 11 | END_PARAGRAPH 12 | end 13 | prog do <<-END_CODE 14 | puts '...você pode dizer aquilo de novo...' 15 | puts '...você pode dizer aquilo de novo...' 16 | END_CODE 17 | end 18 | para do <<-END_PARAGRAPH 19 | Seria legal se pudéssemos digitá-lo uma única vez e mantê-lo por perto... 20 | guardá-lo em algum lugar. 21 | Bom, nós podemos, é claro—caso contrário eu não teria tocado no assunto! 22 | END_PARAGRAPH 23 | end 24 | para do <<-END_PARAGRAPH 25 | Para guardar a string na memória de seu computador, precisamos dar 26 | um nome a ela. Normalmente os programadores chamam esse processo de 27 | atribuição, e chamam os nomes de variáveis. A 28 | variável pode ser praticamente qualquer seqüência de letras e números, 29 | mas o primeiro caracter tem de ser uma letra minúscula. Vamos rodar 30 | o último programa de novo, mas desta vez eu darei à string o nome de 31 | #{code 'minhaString'} (ainda que eu pudesse tê-la chamado de 32 | #{code 'str'} ou #{code 'minhaStringzinha'} ou #{code 'pedroPrimeiro'}). 33 | END_PARAGRAPH 34 | end 35 | prog do <<-END_CODE 36 | minhaString = '...você pode dizer aquilo de novo...' 37 | puts minhaString 38 | puts minhaString 39 | END_CODE 40 | end 41 | para do <<-END_PARAGRAPH 42 | Sempre que você tentou fazer algo com #{code 'minhaString'}, o programa 43 | fez com #{code "'...você pode dizer aquilo de novo'"} no lugar. Você 44 | pode pensar na variável #{code 'minhaString'} como "apontando para" a 45 | string #{code "'...você pode dizer aquilo de novo...'"}. Eis um exemplo 46 | um pouquinho mais interessante: 47 | END_PARAGRAPH 48 | end 49 | prog do <<-END_CODE 50 | nome = 'Patricia Rosanna Jessica Mildred Oppenheimer' 51 | puts 'Meu nome é ' + nome + '.' 52 | puts 'Nossa! ' + nome + ' é um nome bem longo!' 53 | END_CODE 54 | end 55 | para do <<-END_PARAGRAPH 56 | Assim como podemos atribuir um objeto a uma variável, 57 | podemos reatribuir um objeto diferente à mesma variável (e 58 | é por isso que nós as chamamos de variáveis: porque a coisa para 59 | a qual apontam pode variar). 60 | END_PARAGRAPH 61 | end 62 | prog do <<-END_CODE 63 | compositor = 'Mozart' 64 | puts compositor + ' era "sensa", na sua época.' 65 | 66 | compositor = 'Beethoven' 67 | puts 'Mas eu, pessoalmente, prefiro ' + compositor + '.' 68 | END_CODE 69 | end 70 | para do <<-END_PARAGRAPH 71 | Variáveis podem, é claro, apontar para qualquer tipo de objeto, não 72 | só strings: 73 | END_PARAGRAPH 74 | end 75 | prog do <<-END_CODE 76 | var = 'só mais uma ' + 'string' 77 | puts var 78 | 79 | var = 5 * (1+2) 80 | puts var 81 | END_CODE 82 | end 83 | para do <<-END_PARAGRAPH 84 | Na verdade, variáveis podem apontar para qualquer coisa... 85 | que não outras variáveis. 86 | Então o que acontece se tentarmos? 87 | END_PARAGRAPH 88 | end 89 | prog do <<-END_CODE 90 | var1 = 8 91 | var2 = var1 92 | puts var1 93 | puts var2 94 | 95 | puts '' 96 | 97 | var1 = 'oito' 98 | puts var1 99 | puts var2 100 | END_CODE 101 | end 102 | para do <<-END_PARAGRAPH 103 | Primeiro, quando tentamos apontar #{code 'var2'} para #{code 'var1'}, 104 | #{code 'var2'} apontou para #{code '8'} (exatamente como #{code 'var1'} 105 | apontava). Aí fizemos #{code 'var1'} apontar para #{code "'oito'"}, mas 106 | como #{code 'var2'} nunca apontou de verdade para #{code 'var1'}, ela 107 | se mantém apontando para #{code '8'}. 108 | END_PARAGRAPH 109 | end 110 | para do <<-END_PARAGRAPH 111 | Agora que temos variáveis, números e strings, vamos aprender como 112 | #{makeLink 'misturar todos eles', :generateConversion}! 113 | END_PARAGRAPH 114 | end 115 | end 116 | end 117 | -------------------------------------------------------------------------------- /log/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmonteiro/aprendaaprogramar/961a7d32d91480c4e2f4be3b8621c74ec21abf00/log/.gitignore -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | # General Apache options 2 | AddHandler fastcgi-script .fcgi 3 | AddHandler cgi-script .cgi 4 | Options +FollowSymLinks +ExecCGI 5 | 6 | # If you don't want Rails to look in certain directories, 7 | # use the following rewrite rules so that Apache won't rewrite certain requests 8 | # 9 | # Example: 10 | # RewriteCond %{REQUEST_URI} ^/notrails.* 11 | # RewriteRule .* - [L] 12 | 13 | # Redirect all requests not available on the filesystem to Rails 14 | # By default the cgi dispatcher is used which is very slow 15 | # 16 | # For better performance replace the dispatcher with the fastcgi one 17 | # 18 | # Example: 19 | # RewriteRule ^(.*)$ dispatch.fcgi [QSA,L] 20 | RewriteEngine On 21 | 22 | # If your Rails application is accessed via an Alias directive, 23 | # then you MUST also set the RewriteBase in this htaccess file. 24 | # 25 | # Example: 26 | # Alias /myrailsapp /path/to/myrailsapp/public 27 | # RewriteBase /myrailsapp 28 | 29 | RewriteRule ^$ index.html [QSA] 30 | RewriteRule ^([^.]+)$ $1.html [QSA] 31 | RewriteCond %{REQUEST_FILENAME} !-f 32 | RewriteRule ^(.*)$ dispatch.cgi [QSA,L] 33 | 34 | # In case Rails experiences terminal errors 35 | # Instead of displaying this message you can supply a file here which will be rendered instead 36 | # 37 | # Example: 38 | # ErrorDocument 500 /500.html 39 | 40 | ErrorDocument 500 "

Application error

Rails application failed to start properly" 41 | -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | The page you were looking for doesn't exist (404) 9 | 21 | 22 | 23 | 24 | 25 |
26 |

The page you were looking for doesn't exist.

27 |

You may have mistyped the address or the page may have moved.

28 |
29 | 30 | -------------------------------------------------------------------------------- /public/422.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | The change you wanted was rejected (422) 9 | 21 | 22 | 23 | 24 | 25 |
26 |

The change you wanted was rejected.

27 |

Maybe you tried to change something you didn't have access to.

28 |
29 | 30 | -------------------------------------------------------------------------------- /public/500.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | We're sorry, but something went wrong (500) 9 | 21 | 22 | 23 | 24 | 25 |
26 |

We're sorry, but something went wrong.

27 |

We've been notified about this issue and we'll take a look at it shortly.

28 |
29 | 30 | -------------------------------------------------------------------------------- /public/SciTEGlobal.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmonteiro/aprendaaprogramar/961a7d32d91480c4e2f4be3b8621c74ec21abf00/public/SciTEGlobal.properties -------------------------------------------------------------------------------- /public/dispatch.cgi: -------------------------------------------------------------------------------- 1 | #!/opt/local/bin/ruby 2 | 3 | require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT) 4 | 5 | # If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like: 6 | # "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired 7 | require "dispatcher" 8 | 9 | ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun) 10 | Dispatcher.dispatch -------------------------------------------------------------------------------- /public/dispatch.fcgi: -------------------------------------------------------------------------------- 1 | #!/opt/local/bin/ruby 2 | # 3 | # You may specify the path to the FastCGI crash log (a log of unhandled 4 | # exceptions which forced the FastCGI instance to exit, great for debugging) 5 | # and the number of requests to process before running garbage collection. 6 | # 7 | # By default, the FastCGI crash log is RAILS_ROOT/log/fastcgi.crash.log 8 | # and the GC period is nil (turned off). A reasonable number of requests 9 | # could range from 10-100 depending on the memory footprint of your app. 10 | # 11 | # Example: 12 | # # Default log path, normal GC behavior. 13 | # RailsFCGIHandler.process! 14 | # 15 | # # Default log path, 50 requests between GC. 16 | # RailsFCGIHandler.process! nil, 50 17 | # 18 | # # Custom log path, normal GC behavior. 19 | # RailsFCGIHandler.process! '/var/log/myapp_fcgi_crash.log' 20 | # 21 | require File.dirname(__FILE__) + "/../config/environment" 22 | require 'fcgi_handler' 23 | 24 | RailsFCGIHandler.process! 25 | -------------------------------------------------------------------------------- /public/dispatch.rb: -------------------------------------------------------------------------------- 1 | #!/opt/local/bin/ruby 2 | 3 | require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT) 4 | 5 | # If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like: 6 | # "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired 7 | require "dispatcher" 8 | 9 | ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun) 10 | Dispatcher.dispatch -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmonteiro/aprendaaprogramar/961a7d32d91480c4e2f4be3b8621c74ec21abf00/public/favicon.ico -------------------------------------------------------------------------------- /public/images/LTP_cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmonteiro/aprendaaprogramar/961a7d32d91480c4e2f4be3b8621c74ec21abf00/public/images/LTP_cover.jpg -------------------------------------------------------------------------------- /public/images/PoweredByRuby.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmonteiro/aprendaaprogramar/961a7d32d91480c4e2f4be3b8621c74ec21abf00/public/images/PoweredByRuby.png -------------------------------------------------------------------------------- /public/images/fleur_right.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmonteiro/aprendaaprogramar/961a7d32d91480c4e2f4be3b8621c74ec21abf00/public/images/fleur_right.gif -------------------------------------------------------------------------------- /public/images/flowerborder.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmonteiro/aprendaaprogramar/961a7d32d91480c4e2f4be3b8621c74ec21abf00/public/images/flowerborder.gif -------------------------------------------------------------------------------- /public/images/locketLTP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmonteiro/aprendaaprogramar/961a7d32d91480c4e2f4be3b8621c74ec21abf00/public/images/locketLTP.png -------------------------------------------------------------------------------- /public/images/paper_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmonteiro/aprendaaprogramar/961a7d32d91480c4e2f4be3b8621c74ec21abf00/public/images/paper_background.png -------------------------------------------------------------------------------- /public/images/rails.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmonteiro/aprendaaprogramar/961a7d32d91480c4e2f4be3b8621c74ec21abf00/public/images/rails.png -------------------------------------------------------------------------------- /public/images/shadowS.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmonteiro/aprendaaprogramar/961a7d32d91480c4e2f4be3b8621c74ec21abf00/public/images/shadowS.gif -------------------------------------------------------------------------------- /public/images/speardown_sm.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmonteiro/aprendaaprogramar/961a7d32d91480c4e2f4be3b8621c74ec21abf00/public/images/speardown_sm.gif -------------------------------------------------------------------------------- /public/images/spearup_sm.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmonteiro/aprendaaprogramar/961a7d32d91480c4e2f4be3b8621c74ec21abf00/public/images/spearup_sm.gif -------------------------------------------------------------------------------- /public/images/swirly.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmonteiro/aprendaaprogramar/961a7d32d91480c4e2f4be3b8621c74ec21abf00/public/images/swirly.gif -------------------------------------------------------------------------------- /public/images/titleLTP.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmonteiro/aprendaaprogramar/961a7d32d91480c4e2f4be3b8621c74ec21abf00/public/images/titleLTP.gif -------------------------------------------------------------------------------- /public/images/titleLTP_pt_br.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmonteiro/aprendaaprogramar/961a7d32d91480c4e2f4be3b8621c74ec21abf00/public/images/titleLTP_pt_br.gif -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-Agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /public/ruby.properties: -------------------------------------------------------------------------------- 1 | # Define SciTE settings for Ruby files. 2 | 3 | file.patterns.rb=*.rb;*.rbw;*.rbx 4 | 5 | filter.ruby=Ruby (rb rbw rbx)|$(file.patterns.rb)| 6 | 7 | lexer.$(file.patterns.rb)=ruby 8 | 9 | keywordclass.ruby=__FILE__ and def end in or self unless __LINE__ begin \ 10 | defined? ensure module redo super until BEGIN break do false next rescue \ 11 | then when END case else for nil retry true while alias class elsif if \ 12 | not return undef yield 13 | keywords.$(file.patterns.rb)=$(keywordclass.ruby) 14 | 15 | statement.indent.*.rb= 16 | statement.end*.rb= 17 | statement.lookback.*.rb=1 18 | block.start.*.rb=10 19 | 20 | comment.block.ruby=#~ 21 | 22 | # ruby styles 23 | # White space 24 | style.ruby.0=fore:#0000FF 25 | # Comment 26 | style.ruby.1=fore:#FFFFFF,$(font.comment) 27 | # Number 28 | style.ruby.2=fore:#007F00 29 | # String 30 | style.ruby.3=fore:#C00000,$(font.monospace) 31 | # Single quoted string 32 | style.ruby.4=fore:#C00000,$(font.monospace) 33 | # Keyword 34 | style.ruby.5=fore:#0000FF 35 | # Triple quotes 36 | style.ruby.6=fore:#FFFFFF 37 | # Triple double quotes 38 | style.ruby.7=fore:#FFFFFF 39 | # Class name definition 40 | style.ruby.8=fore:#7F007F 41 | # Function or method name definition 42 | style.ruby.9=fore:#7F007F 43 | # Operators 44 | #style.ruby.10=bold 45 | # Identifiers 46 | style.ruby.11=fore:#000000 47 | # Comment-blocks 48 | style.ruby.12=fore:#FFFFFF 49 | # End of line where string is not closed 50 | style.ruby.13=fore:#000000,$(font.monospace),back:#E0C0E0,eolfilled 51 | # Matched Operators 52 | #style.ruby.34=fore:bold 53 | #style.ruby.35=fore:#FF0000 54 | # Braces are only matched in operator style 55 | braces.ruby.style=10 56 | 57 | if PLAT_WIN 58 | command.go.*.rb=ruby $(FileNameExt) 59 | command.go.subsystem.*.rb=1 60 | 61 | if PLAT_GTK 62 | command.go.*.rb=ruby $(FileNameExt) 63 | -------------------------------------------------------------------------------- /public/stylesheets/pine.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | color: #403b31; 4 | background: #f6f4e3 url(../images/paper_background.png); 5 | } 6 | 7 | * 8 | { 9 | margin: 0px; 10 | padding: 0px; 11 | border: 0px; 12 | } 13 | 14 | body, p, ol, ul, td 15 | { 16 | /*font-family: verdana, arial, helvetica, sans-serif;*/ 17 | font-family: palatino, bookman, "Bookman Old Style", "Book Antiqua", serif; 18 | font-size: 15px; 19 | /*line-height: 18px;*/ 20 | } 21 | 22 | 23 | blockquote 24 | { 25 | padding: 5px; 26 | padding-left: 0px; 27 | margin: 7px; 28 | margin-left: 17px; 29 | font-size: 12px; 30 | font-style: italic; 31 | /*border-left: 2px solid #db9;*/ 32 | } 33 | blockquote em { font-style: normal; } 34 | blockquote p { font-size: 12px; } 35 | 36 | 37 | p, ol, ul { padding: 5px; } 38 | img { display: block; } 39 | 40 | a { color: #3a4; } 41 | a:visited { color: #807b71; } 42 | a:hover { color: #3b4; /*background-color:#000;*/ } 43 | 44 | acronym { border-bottom: 1px dotted black; } 45 | 46 | .domhidden { display: none; } 47 | 48 | #debugModeWarning 49 | { 50 | position: fixed; 51 | top: 35px; 52 | left: 30px; 53 | z-index: 5; 54 | } 55 | 56 | #debugModeWarningInnerDiv 57 | { 58 | font-size: 20px; 59 | font-family: vinque, dungeon; 60 | color: #a00; 61 | } 62 | 63 | #pageWidth 64 | { 65 | width: 100%; 66 | min-width: 500px; 67 | } 68 | 69 | #locket 70 | { 71 | position: absolute; 72 | top: 15px; 73 | right: 15px; 74 | } 75 | 76 | #headerBar 77 | { 78 | height:122px; 79 | width:100%; 80 | position: absolute; 81 | top: 0px; 82 | left: 0px; 83 | background: #403b31 url(../images/flowerborder.gif) bottom repeat-x; 84 | } 85 | 86 | #titlePicContainer 87 | { 88 | position: relative; 89 | left: 50%; 90 | width: 50%; 91 | } 92 | #titlePic 93 | { 94 | position: relative; 95 | top: 2px; 96 | left: -258px; 97 | /*color: #d8c0a0;*/ 98 | } 99 | 100 | #menuPane 101 | { 102 | position: absolute; 103 | top: 150px; 104 | width: 190px; 105 | left: 25px; 106 | padding: 8px; 107 | } 108 | 109 | #menuPane img 110 | { 111 | margin-left: auto; 112 | margin-right: auto; 113 | position: relative; 114 | left: -10px; 115 | } 116 | 117 | #menuPane a { text-decoration: none; font-weight: bold; } 118 | #menuPane a:visited { color: #3a4; font-weight: bold; } 119 | #menuPane a:hover { color: #3b4; text-decoration: underline; font-weight: bold; } 120 | 121 | #menuPane a.stealth_link { color: #403b31; font-weight: normal; } 122 | #menuPane a.stealth_link:visited { color: #403b31; } 123 | #menuPane a.stealth_link:hover { color: #3b4; } 124 | 125 | #menuSpearTop 126 | { 127 | padding-bottom: 30px; /* space between spear and menu content */ 128 | } 129 | 130 | #menuSpearBottom 131 | { 132 | top: 30px; /* space between spear and menu content */ 133 | } 134 | 135 | #menuPane p, ul, ol 136 | { 137 | /*letter-spacing: 1px;*/ 138 | font-size: 10px; 139 | font-family: verdana, tahoma, helvetica, arial, sans-serif; 140 | line-height: 1.3; 141 | } 142 | 143 | .funnyMenuText 144 | { 145 | text-align: center; 146 | position: relative; 147 | left: -12px; 148 | } 149 | 150 | #contentPane 151 | { 152 | position: absolute; 153 | top: 160px; 154 | left: 260px; 155 | right: 40px; 156 | } 157 | 158 | #contentPane p 159 | { 160 | line-height: 120%; 161 | clear: both; 162 | padding-left: 15px; 163 | } 164 | 165 | .blogview 166 | { 167 | margin: 5px; 168 | clear: both; 169 | } 170 | 171 | .latest_comment_date 172 | { 173 | font-size: 14px; 174 | line-height: 100%; 175 | font-style: italic; 176 | clear: both; 177 | color: #706645; 178 | padding-bottom: 24px; 179 | padding-top: 0px; 180 | padding-left: 40px; 181 | margin-top: -12px; 182 | } 183 | 184 | .picture_caption 185 | { 186 | font-size: 14px; 187 | line-height: 100%; 188 | font-style: italic; 189 | color: #706645; 190 | padding-left: 15px; 191 | padding-bottom: 5px; 192 | clear: both; 193 | } 194 | 195 | .photo_caption 196 | { 197 | font-size: 14px; 198 | line-height: 100%; 199 | font-style: italic; 200 | color: #706645; 201 | } 202 | 203 | .fleur 204 | { 205 | clear: both; 206 | background: url(../images/fleur_right.gif) bottom right no-repeat; 207 | padding-bottom: 20px; /* Needs to be 20px for the fleur stem. */ 208 | } 209 | 210 | .fleur_stem 211 | { 212 | padding-bottom: 10px; /* Controls blank space above the fleur. */ 213 | margin-right: 30px; /* Needs to be 30px for the fleur stem. */ 214 | border-bottom-width: 1px; 215 | border-style: solid; 216 | border-color: #706645; 217 | } 218 | 219 | .commenter 220 | { 221 | font-size: 17px; 222 | clear: both; 223 | color: #706645; 224 | padding: 5px; 225 | padding-left: 35px; /* Controls horizontal positioning of the name relative to dash (should be about 35px). */ 226 | padding-bottom: 17px; 227 | margin-top: -22px; 228 | margin-left: 30px; /* Controls horizontal positioning of the name-dash combo. */ 229 | /*content: "hootie"*/ 230 | } 231 | /*.commenter::after 232 | { 233 | content: " said it" 234 | }*/ 235 | 236 | .commenter img 237 | { 238 | display: inline; 239 | position: relative; 240 | top: 13px; 241 | } 242 | 243 | .name_header 244 | { 245 | font-size: 35px; 246 | letter-spacing: 2px; 247 | font-weight: bolder; 248 | font-style: italic; 249 | color: #706645; 250 | padding-left: 50px; 251 | } 252 | 253 | h1 254 | { 255 | font-size: 25px; 256 | text-align: center; 257 | letter-spacing: 2px; 258 | font-variant: small-caps; 259 | font-weight: bolder; 260 | color: #706645; 261 | margin-bottom: 20px; 262 | padding-top: 20px; /* Controls blank space below the fleur. */ 263 | } 264 | 265 | h2 266 | { 267 | font-size: 20px; 268 | letter-spacing: 2px; 269 | font-variant: small-caps; 270 | font-weight: bolder; 271 | color: #706645; 272 | margin-bottom: 20px; 273 | padding-top: 20px; /* Controls blank space below the fleur. */ 274 | padding-left: 20px; 275 | } 276 | 277 | h3 278 | { 279 | position: relative; 280 | left: 10px; 281 | padding: 15px; 282 | } 283 | 284 | .shadow_corner 285 | { 286 | z-index: 1; 287 | width: 7px; 288 | position: absolute; 289 | } 290 | 291 | .shadow_nw 292 | { 293 | height: 6px; 294 | } 295 | 296 | .shadow_ne 297 | { 298 | height: 6px; 299 | right: 0px; 300 | } 301 | 302 | .shadow_sw 303 | { 304 | height: 8px; 305 | bottom: 0px; 306 | } 307 | 308 | .shadow_se 309 | { 310 | height: 8px; 311 | right: 0px; 312 | bottom: 0px; 313 | } 314 | 315 | .photo 316 | { 317 | z-index: -1; 318 | padding: 5px 5px 8px 5px; 319 | background: #ffffff url(../images/shadowS.gif) repeat-x bottom left; 320 | } 321 | 322 | .photo_and_shadow 323 | { 324 | margin: 5px; 325 | float: left; 326 | position: relative; 327 | } 328 | 329 | .shadow_edges 330 | { 331 | background: #abaa9e; 332 | padding: 0px 1px 0px 1px; 333 | border: 1px solid #dfddce; 334 | border-bottom: 0px; 335 | } 336 | 337 | .form_text_field 338 | { 339 | background: #f9f8f0; 340 | padding: .25em; 341 | margin: .15em; 342 | border: 1px solid #a3895c; 343 | } 344 | 345 | .form_drop_down 346 | { 347 | background: #f9f8f0; 348 | border: 1px solid #a3895c; 349 | } 350 | 351 | .form_text_area 352 | { 353 | background: #f9f8f0; 354 | border: 1px solid #a3895c; 355 | padding: .25em; 356 | } 357 | 358 | .formatting_tips 359 | { 360 | float: left; 361 | margin-left: 30px; 362 | } 363 | 364 | .button 365 | { 366 | border: 3px double #999999; 367 | border-top-color: #CCCCCC; 368 | border-left-color: #CCCCCC; 369 | padding: 0.15em; 370 | margin: 5px 0px 5px 20px; 371 | background-color: #f9f8f0; 372 | color: #403b31; 373 | font-size: 75%; 374 | font-weight: bold; 375 | font-family: palatino, bookman, "Bookman Old Style", "Book Antiqua", serif; 376 | } 377 | 378 | /*********************************** 379 | ******** Rails Stuff below ******** 380 | ***********************************/ 381 | 382 | .fieldWithErrors { 383 | padding: 2px; 384 | background-color: red; 385 | display: table; 386 | } 387 | 388 | #ErrorExplanation { 389 | width: 400px; 390 | border: 2px solid red; 391 | padding: 7px; 392 | padding-bottom: 12px; 393 | margin-bottom: 20px; 394 | background-color: #f0f0f0; 395 | } 396 | 397 | #ErrorExplanation h2 { 398 | text-align: left; 399 | font-weight: bold; 400 | padding: 5px 5px 5px 15px; 401 | font-size: 12px; 402 | margin: -7px; 403 | background-color: #c00; 404 | color: #fff; 405 | } 406 | 407 | #ErrorExplanation p { 408 | color: #333; 409 | margin-bottom: 0; 410 | padding: 5px; 411 | } 412 | 413 | #ErrorExplanation ul li { 414 | font-size: 12px; 415 | list-style: square; 416 | } 417 | 418 | div.uploadStatus { 419 | margin: 5px; 420 | } 421 | 422 | div.progressBar { 423 | margin: 5px; 424 | } 425 | 426 | div.progressBar div.border { 427 | background-color: #fff; 428 | border: 1px solid grey; 429 | width: 100%; 430 | } 431 | 432 | div.progressBar div.background { 433 | background-color: #333; 434 | height: 18px; 435 | width: 0%; 436 | } 437 | 438 | -------------------------------------------------------------------------------- /public/stylesheets/print.css: -------------------------------------------------------------------------------- 1 | #menuPane 2 | { 3 | display: none; 4 | } 5 | #titlePicContainer 6 | { 7 | position: relative; 8 | left: 50%; 9 | width: 50%; 10 | } 11 | #titlePicContainer a img { 12 | border: 0; 13 | } 14 | #titlePic 15 | { 16 | position: relative; 17 | top: 2px; 18 | left: -256px; 19 | /*color: #d8c0a0;*/ 20 | } 21 | #locket 22 | { 23 | position: absolute; 24 | top: 15px; 25 | right: 15px; 26 | } 27 | -------------------------------------------------------------------------------- /public/stylesheets/tutorial.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | #menuPane 4 | { 5 | position: absolute; 6 | top: 150px; 7 | width: 190px; 8 | left: 25px; 9 | padding: 8px; 10 | } 11 | 12 | 13 | #menuPane a { text-decoration: none; font-weight: normal; } 14 | #menuPane a:visited { color: #3a4; font-weight: normal; } 15 | #menuPane a:hover { color: #3b4; text-decoration: underline; font-weight: normal; } 16 | 17 | 18 | #menuPane p, ul, ol 19 | { 20 | font-size: 10px; 21 | font-family: verdana, tahoma, helvetica, arial, sans-serif; 22 | line-height: 1.3; 23 | } 24 | 25 | .funnyMenuText 26 | { 27 | text-align: center; 28 | position: relative; 29 | left: -10px; 30 | } 31 | 32 | .fancyMenuText 33 | { 34 | letter-spacing: 1px; 35 | padding: 0px; 36 | padding-bottom: 5px; 37 | margin-top: -5px; 38 | } 39 | 40 | 41 | h1 42 | { 43 | font-size: 25px; 44 | text-align: center; 45 | letter-spacing: 2px; 46 | font-variant: small-caps; 47 | font-weight: bolder; 48 | color: #706645; 49 | margin-bottom: 20px; 50 | padding-top: 20px; /* Controls blank space below the fleur. */ 51 | } 52 | 53 | h2 54 | { 55 | font-size: 20px; 56 | letter-spacing: 2px; 57 | font-variant: small-caps; 58 | font-weight: bolder; 59 | color: #706645; 60 | margin-bottom: 20px; 61 | padding-top: 20px; /* Controls blank space below the fleur. */ 62 | padding-left: 20px; 63 | } 64 | 65 | h3 66 | { 67 | position: relative; 68 | left: 10px; 69 | padding: 15px; 70 | } 71 | 72 | 73 | /*********************************** 74 | ********** L2P Stuff below ********* 75 | ***********************************/ 76 | 77 | pre 78 | { 79 | padding: 10px; 80 | margin: 20px; 81 | width: 90%; 82 | } 83 | 84 | .L2Pinput 85 | { 86 | border-right: #d0b0b0 1px solid; 87 | border-top: #907070 1px solid; 88 | border-left: #705050 1px solid; 89 | border-bottom: #c0a0a0 1px solid; 90 | padding-right: 3px; 91 | padding-top: 0px; 92 | padding-left: 3px; 93 | padding-bottom: 0px; 94 | white-space: pre; 95 | font-family: courier new, monospace; 96 | background-color: #f3f4f6; 97 | } 98 | 99 | .L2Pcode 100 | { 101 | padding-right: 0px; 102 | padding-top: 0px; 103 | padding-left: 0px; 104 | padding-bottom: 0px; 105 | white-space: pre; 106 | font-family: courier new, monospace; 107 | font-weight: 600; 108 | } 109 | 110 | .L2PcodeBG 111 | { 112 | background-color: #c6d2e8; 113 | } 114 | 115 | .L2PcodeBlock 116 | { 117 | background-color: #d2cbbe; 118 | border-right: #fffbee 1px solid; 119 | border-top: #b2ab9e 1px solid; 120 | border-left: #a29b8e 1px solid; 121 | border-bottom: #f2ebde 1px solid; 122 | } 123 | 124 | .L2PoutputBlock 125 | { 126 | background-color: #c6d2e8; 127 | border-right: #909aba 1px solid; 128 | border-top: #d6e2ff 1px solid; 129 | border-left: #e3f2f4 1px solid; 130 | border-bottom: #a0aaca 1px solid; 131 | } 132 | 133 | .L2Pstring 134 | { 135 | color: #c00000; 136 | } 137 | 138 | .L2Pnumber 139 | { 140 | color: #007f00; 141 | } 142 | 143 | .L2Pkeyword 144 | { 145 | color: #0000ff; 146 | } 147 | 148 | .L2Pdefinition 149 | { 150 | color: #7f007f; 151 | } 152 | 153 | .L2Pcomment 154 | { 155 | color: #ffffff; 156 | } 157 | 158 | -------------------------------------------------------------------------------- /script/about: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | require 'commands/about' 4 | -------------------------------------------------------------------------------- /script/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | require 'commands/console' 4 | -------------------------------------------------------------------------------- /script/destroy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | require 'commands/destroy' 4 | -------------------------------------------------------------------------------- /script/generate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | require 'commands/generate' 4 | -------------------------------------------------------------------------------- /script/performance/benchmarker: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../../config/boot' 3 | require 'commands/performance/benchmarker' 4 | -------------------------------------------------------------------------------- /script/performance/profiler: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../../config/boot' 3 | require 'commands/performance/profiler' 4 | -------------------------------------------------------------------------------- /script/performance/request: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../../config/boot' 3 | require 'commands/performance/request' 4 | -------------------------------------------------------------------------------- /script/plugin: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | require 'commands/plugin' 4 | -------------------------------------------------------------------------------- /script/process/inspector: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../../config/boot' 3 | require 'commands/process/inspector' 4 | -------------------------------------------------------------------------------- /script/process/reaper: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../../config/boot' 3 | require 'commands/process/reaper' 4 | -------------------------------------------------------------------------------- /script/process/spawner: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../../config/boot' 3 | require 'commands/process/spawner' 4 | -------------------------------------------------------------------------------- /script/runner: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | require 'commands/runner' 4 | -------------------------------------------------------------------------------- /script/server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | require 'commands/server' 4 | -------------------------------------------------------------------------------- /test/functional/learn_controller_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../test_helper' 2 | 3 | class LearnControllerTest < ActionController::TestCase 4 | # Replace this with your real tests. 5 | def test_truth 6 | assert true 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | ENV["RAILS_ENV"] = "test" 2 | require File.expand_path(File.dirname(__FILE__) + "/../config/environment") 3 | require 'test_help' 4 | 5 | class Test::Unit::TestCase 6 | # Transactional fixtures accelerate your tests by wrapping each test method 7 | # in a transaction that's rolled back on completion. This ensures that the 8 | # test database remains unchanged so your fixtures don't have to be reloaded 9 | # between every test method. Fewer database queries means faster tests. 10 | # 11 | # Read Mike Clark's excellent walkthrough at 12 | # http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting 13 | # 14 | # Every Active Record database supports transactions except MyISAM tables 15 | # in MySQL. Turn off transactional fixtures in this case; however, if you 16 | # don't care one way or the other, switching from MyISAM to InnoDB tables 17 | # is recommended. 18 | # 19 | # The only drawback to using transactional fixtures is when you actually 20 | # need to test transactions. Since your test is bracketed by a transaction, 21 | # any transactions started in your code will be automatically rolled back. 22 | self.use_transactional_fixtures = true 23 | 24 | # Instantiated fixtures are slow, but give you @david where otherwise you 25 | # would need people(:david). If you don't want to migrate your existing 26 | # test cases which use the @david style and don't mind the speed hit (each 27 | # instantiated fixtures translates to a database query per test method), 28 | # then set this back to true. 29 | self.use_instantiated_fixtures = false 30 | 31 | # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order. 32 | # 33 | # Note: You'll currently still have to declare fixtures explicitly in integration tests 34 | # -- they do not yet inherit this setting 35 | fixtures :all 36 | 37 | # Add more helper methods to be used by all tests here... 38 | end 39 | --------------------------------------------------------------------------------